874 lines
26 KiB
C
874 lines
26 KiB
C
/******************************************************************************
|
|
|
|
Copyright (C) Microsoft Corporation 1985-1990. All rights reserved.
|
|
|
|
Title: drvrrare.c - Installable driver code. Less common code
|
|
|
|
Version: 1.00
|
|
|
|
Date: 10-Jun-1990
|
|
|
|
Author: DAVIDDS ROBWI
|
|
|
|
*****************************************************************************/
|
|
|
|
#include <windows.h>
|
|
#include "drvr.h"
|
|
#define MMNOSOUND
|
|
#define MMNOWAVE
|
|
#define MMNOMIDI
|
|
#define MMNOSEQ
|
|
#define MMNOTIMER
|
|
#define MMNOJOY
|
|
#define MMNOMCI
|
|
#include "mmsystem.h"
|
|
#define NOTIMERDEV
|
|
#define NOJOYDEV
|
|
#define NOMCIDEV
|
|
#define NOSEQDEV
|
|
#define NOWAVEDEV
|
|
#define NOMIDIDEV
|
|
#define NOTASKDEV
|
|
#include "mmddk.h"
|
|
#include "mmsysi.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, HANDLE hdrv, WORD msg, DWORD dw1, DWORD dw2);
|
|
|
|
/* Support for using 3.1 APIs if available */
|
|
|
|
typedef HANDLE (FAR PASCAL *OPENDRIVER31)(LPSTR, LPSTR, LONG);
|
|
typedef LONG (FAR PASCAL *CLOSEDRIVER31)(HANDLE, LONG, LONG);
|
|
typedef HANDLE (FAR PASCAL *GETDRIVERMODULEHANDLE31)(HANDLE);
|
|
typedef LONG (FAR PASCAL *SENDDRIVERMESSAGE31)(HANDLE, WORD, LONG, LONG);
|
|
typedef LONG (FAR PASCAL *DEFDRIVERPROC31)(DWORD, HANDLE, WORD, LONG, LONG);
|
|
|
|
OPENDRIVER31 lpOpenDriver;
|
|
CLOSEDRIVER31 lpCloseDriver;
|
|
GETDRIVERMODULEHANDLE31 lpGetDriverModuleHandle;
|
|
SENDDRIVERMESSAGE31 lpSendDriverMessage;
|
|
DEFDRIVERPROC31 lpDefDriverProc;
|
|
BOOL fUseWinAPI;
|
|
|
|
#pragma alloc_text( INIT, DrvInit )
|
|
|
|
/***************************************************************************
|
|
|
|
strings
|
|
|
|
****************************************************************************/
|
|
|
|
extern char far szSystemIni[]; // INIT.C
|
|
extern char far szDrivers[];
|
|
extern char far szBoot[];
|
|
extern char far szNull[];
|
|
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[];
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @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 LONG | lParam1 | Specifies the first message parameter for
|
|
* the DRV_CLOSE message. This data is passed directly to the driver.
|
|
*
|
|
* @parm LONG | 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
|
|
*
|
|
***************************************************************************/
|
|
|
|
|
|
LONG API DrvClose(HANDLE hDriver, LONG lParam1, LONG 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(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 LONG | 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 WORD | 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 API DrvOpen(LPSTR szDriverName,
|
|
LPSTR szSectionName,
|
|
LONG 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
|
|
*/
|
|
|
|
HANDLE hdrv;
|
|
|
|
if (fUseWinAPI)
|
|
hdrv = ((*lpOpenDriver)(szDriverName, szSectionName, lParam2));
|
|
else
|
|
hdrv = (HANDLE)InternalOpenDriver(szDriverName, szSectionName, lParam2, TRUE);
|
|
|
|
#ifdef DEBUG
|
|
if (hdrv) {
|
|
char ach[80];
|
|
static SZCODE szFormat[] = "MMSYSTEM: Opened %ls (%ls)\r\n";
|
|
|
|
GetModuleFileName(DrvGetModuleHandle(hdrv), ach, sizeof(ach));
|
|
DPRINTF((szFormat, (LPSTR)szDriverName, (LPSTR)ach));
|
|
}
|
|
#endif
|
|
|
|
return 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.
|
|
*
|
|
***************************************************************************/
|
|
|
|
HANDLE API DrvGetModuleHandle(HANDLE hDriver)
|
|
{
|
|
LPDRIVERTABLE lpdt;
|
|
HANDLE h = 0;
|
|
|
|
if (fUseWinAPI)
|
|
return ((*lpGetDriverModuleHandle)(hDriver));
|
|
|
|
if (hDriver && ((WORD)hDriver <= cInstalledDrivers))
|
|
{
|
|
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
|
|
h = lpdt[hDriver-1].hModule;
|
|
GlobalUnlock(hInstalledDriverList);
|
|
}
|
|
|
|
return(h);
|
|
}
|
|
|
|
|
|
LONG FAR PASCAL InternalCloseDriver(WORD hDriver,
|
|
LONG lParam1,
|
|
LONG lParam2,
|
|
BOOL fSendDisable)
|
|
{
|
|
LPDRIVERTABLE lpdt;
|
|
LONG result;
|
|
HANDLE h;
|
|
int index;
|
|
BOOL f;
|
|
|
|
// check handle in valid range.
|
|
|
|
if (hDriver > cInstalledDrivers)
|
|
return(FALSE);
|
|
|
|
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
|
|
|
|
result = DrvSendMessage(hDriver, DRV_CLOSE, lParam1, lParam2);
|
|
|
|
if (result)
|
|
{
|
|
|
|
// Driver didn't abort close
|
|
|
|
f = lpdt[hDriver-1].fFirstEntry;
|
|
|
|
if (InternalFreeDriver(hDriver, fSendDisable) && f)
|
|
{
|
|
|
|
/* 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.
|
|
*/
|
|
|
|
for (index=0;index<cInstalledDrivers;index++)
|
|
if (lpdt[index].hModule == lpdt[hDriver-1].hModule && !lpdt[index].fFirstEntry)
|
|
{
|
|
lpdt[index].fFirstEntry = 1;
|
|
break;
|
|
}
|
|
}
|
|
|
|
}
|
|
|
|
GlobalUnlock(hInstalledDriverList);
|
|
|
|
return(result);
|
|
}
|
|
|
|
|
|
LONG FAR PASCAL InternalOpenDriver(LPSTR szDriverName,
|
|
LPSTR szSectionName,
|
|
LONG lParam2,
|
|
BOOL fSendEnable)
|
|
{
|
|
int hDriver;
|
|
LPDRIVERTABLE lpdt;
|
|
LONG result;
|
|
HANDLE h;
|
|
char sz[128];
|
|
|
|
if (hDriver = LOWORD(InternalLoadDriver(szDriverName,
|
|
szSectionName,
|
|
sz,
|
|
sizeof(sz),
|
|
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.
|
|
*/
|
|
|
|
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
|
|
lpdt[hDriver-1].dwDriverIdentifier = hDriver;
|
|
GlobalUnlock(hInstalledDriverList);
|
|
|
|
result = DrvSendMessage(hDriver,
|
|
DRV_OPEN,
|
|
(LONG)(LPSTR)sz,
|
|
lParam2);
|
|
if (!result)
|
|
InternalFreeDriver(hDriver, fSendEnable);
|
|
|
|
else
|
|
{
|
|
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
|
|
lpdt[hDriver-1].dwDriverIdentifier = result;
|
|
GlobalUnlock(hInstalledDriverList);
|
|
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 WORD | cbTail | size of supplied buffer.
|
|
*
|
|
* @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
|
|
*
|
|
****************************************************************************/
|
|
|
|
LONG FAR PASCAL InternalLoadDriver(LPSTR szDriverName,
|
|
LPSTR szSectionName,
|
|
LPSTR lpstrTail,
|
|
WORD cbTail,
|
|
BOOL fSendEnable)
|
|
{
|
|
int index;
|
|
LPDRIVERTABLE lpdt;
|
|
LONG result;
|
|
HANDLE h;
|
|
|
|
|
|
/* 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 */
|
|
|
|
if (!hInstalledDriverList)
|
|
h = GlobalAlloc(GHND | GMEM_SHARE, (DWORD)((WORD)sizeof(DRIVERTABLE)));
|
|
|
|
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)((WORD)sizeof(DRIVERTABLE)*(cInstalledDrivers+1)),
|
|
GHND | GMEM_SHARE);
|
|
|
|
if (!h)
|
|
return(0L);
|
|
|
|
cInstalledDrivers++;
|
|
hInstalledDriverList = h;
|
|
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
|
|
|
|
/* find an unused entry in the table */
|
|
|
|
for (index=0;index<cInstalledDrivers;index++)
|
|
{
|
|
if (lpdt->hModule || lpdt->fBusy)
|
|
lpdt++;
|
|
else
|
|
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->fBusy = 1;
|
|
|
|
h = LoadAliasedLibrary(szDriverName,
|
|
szSectionName ? szSectionName : szDrivers,
|
|
szSystemIni,
|
|
lpstrTail,
|
|
cbTail);
|
|
|
|
if (h < 32)
|
|
{
|
|
result = MAKELONG(0,h);
|
|
goto LoadCleanUp;
|
|
}
|
|
|
|
lpdt->lpDriverEntryPoint = (DRIVERPROC)GetProcAddress(h, szDriverProc);
|
|
if (!lpdt->lpDriverEntryPoint)
|
|
{
|
|
// Driver does not have correct entry point
|
|
FreeLibrary(h);
|
|
result = 0L;
|
|
goto LoadCleanUp;
|
|
}
|
|
|
|
// Set hModule here so that GetDrvrUsage() and DrvSendMessage() work
|
|
|
|
lpdt->hModule = h;
|
|
|
|
if (GetDrvrUsage(h) == 1)
|
|
{
|
|
|
|
// First instance of the driver.
|
|
|
|
if (!DrvSendMessage(index+1, DRV_LOAD, 0L, 0L))
|
|
{
|
|
// Driver failed load call.
|
|
lpdt->lpDriverEntryPoint = NULL;
|
|
lpdt->hModule = NULL;
|
|
FreeLibrary(h);
|
|
result = 0L;
|
|
goto LoadCleanUp;
|
|
}
|
|
lpdt->fFirstEntry = 1;
|
|
if (fSendEnable)
|
|
DrvSendMessage(index+1, DRV_ENABLE, 0L, 0L);
|
|
}
|
|
|
|
result = MAKELONG(index+1,h);
|
|
|
|
LoadCleanUp:
|
|
lpdt->fBusy = 0;
|
|
GlobalUnlock(hInstalledDriverList);
|
|
return(result);
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @doc INTERNAL
|
|
*
|
|
* @api WORD | 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
|
|
*
|
|
***************************************************************************/
|
|
|
|
WORD FAR PASCAL InternalFreeDriver(WORD hDriver, BOOL fSendDisable)
|
|
{
|
|
LPDRIVERTABLE lpdt;
|
|
HANDLE h;
|
|
WORD w;
|
|
|
|
/* The driver will receive the following message sequence:
|
|
*
|
|
* if usage count of driver is 1
|
|
* DRV_DISABLE (normally)
|
|
* DRV_FREE
|
|
*/
|
|
|
|
if (hDriver > cInstalledDrivers || !hDriver)
|
|
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;
|
|
|
|
w = GetDrvrUsage(lpdt[hDriver-1].hModule);
|
|
if (w == 1)
|
|
{
|
|
if (fSendDisable)
|
|
DrvSendMessage(hDriver, DRV_DISABLE, 0L, 0L);
|
|
DrvSendMessage(hDriver, DRV_FREE, 0L, 0L);
|
|
}
|
|
FreeLibrary(lpdt[hDriver-1].hModule);
|
|
|
|
// 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);
|
|
return(w-1);
|
|
}
|
|
|
|
#ifdef DEBUG
|
|
|
|
WORD GetWinVer()
|
|
{
|
|
WORD w = GetVersion();
|
|
|
|
return (w>>8) | (w<<8);
|
|
}
|
|
|
|
#endif
|
|
|
|
void NEAR PASCAL DrvInit(void)
|
|
{
|
|
HANDLE hlibUser;
|
|
LPDRIVERTABLE lpdt;
|
|
|
|
/* If the window's driver interface is present then use it.
|
|
*/
|
|
|
|
DOUT("MMSYSTEM: DrvInit");
|
|
|
|
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 enableing it.
|
|
//
|
|
cInstalledDrivers = 1;
|
|
hInstalledDriverList = GlobalAlloc(GHND|GMEM_SHARE, (DWORD)((WORD)sizeof(DRIVERTABLE)));
|
|
|
|
#ifdef DEBUG
|
|
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);
|
|
}
|
|
|
|
if (fUseWinAPI)
|
|
{
|
|
DOUT(" - Windows Driver I/F detected\r\n");
|
|
|
|
#ifdef DEBUG
|
|
if (GetWinVer() < 0x30A)
|
|
DOUT("MMSYSTEM: WARNING !!! WINDOWS DRIVER I/F BUT VERSION LESS THAN 3.1\r\n");
|
|
#endif
|
|
|
|
// 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);
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @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
|
|
*/
|
|
GetPrivateProfileString(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;
|
|
}
|
|
}
|
|
}
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @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 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 WORD | cbTail | size of supplied buffer.
|
|
*
|
|
* @rdesc Returns the library's module handle.
|
|
*
|
|
* @xref LoadLibrary
|
|
*
|
|
***************************************************************************/
|
|
|
|
HANDLE FAR PASCAL LoadAliasedLibrary(LPSTR szLibFileName,
|
|
LPSTR szSection,
|
|
LPSTR szIniFile,
|
|
LPSTR lpstrTail,
|
|
WORD cbTail)
|
|
{
|
|
HANDLE h;
|
|
char sz[128];
|
|
LPSTR pch;
|
|
OFSTRUCT of;
|
|
|
|
if (!szLibFileName || !*szLibFileName)
|
|
return(2); // File not found
|
|
|
|
// read the filename and additional info. into sz
|
|
|
|
GetPrivateProfileString(szSection, // ini section
|
|
szLibFileName, // key name
|
|
szLibFileName, // default if no match
|
|
sz, // return buffer
|
|
sizeof(sz), // return buffer size
|
|
szIniFile); // ini. file
|
|
|
|
sz[sizeof(sz)-1] = 0;
|
|
|
|
// strip off the additional info.
|
|
|
|
pch = (LPSTR)sz;
|
|
|
|
while (*pch)
|
|
{
|
|
if (*pch == ' ')
|
|
{
|
|
*pch++ = '\0';
|
|
break;
|
|
}
|
|
pch++;
|
|
}
|
|
|
|
// pch pts to ch after first space or null ch
|
|
|
|
if (!GetModuleHandle(sz) &&
|
|
OpenFile(sz, &of, OF_EXIST|OF_READ|OF_SHARE_DENY_NONE) == -1)
|
|
return(2);
|
|
|
|
// copy additional info. to lpstrTail
|
|
|
|
if (lpstrTail && cbTail)
|
|
{
|
|
while (cbTail-- && (*lpstrTail++ = *pch++))
|
|
;
|
|
*(lpstrTail-1) = 0;
|
|
}
|
|
|
|
return (LoadLibrary(sz));
|
|
}
|
|
|
|
|
|
/***************************************************************************
|
|
*
|
|
* @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;
|
|
|
|
if (!hInstalledDriverList || !cInstalledDrivers)
|
|
return(0);
|
|
|
|
count = 0;
|
|
lpdt = (LPDRIVERTABLE)GlobalLock(hInstalledDriverList);
|
|
for (index=0;index<cInstalledDrivers;index++)
|
|
{
|
|
if (lpdt->hModule==h)
|
|
{
|
|
count++;
|
|
}
|
|
lpdt++;
|
|
}
|
|
GlobalUnlock(hInstalledDriverList);
|
|
|
|
return(count);
|
|
}
|