I've been looking at the various steam driver examples included with CE 6.0,
but they all seem be interrupt driven, where the IST threads wait on the
interrupt. Is there a problem with calling Sleep() within a thread created
by a kernel mode driver?
Here is my driver registry settings and the cut down code that still has the
abort occurring.
[HKEY_LOCAL_MACHINE\Drivers\BuiltIn\Bsd]
"Dll"="bsd.Dll"
"Prefix"="BSD"
"Order"=dword:2
"IoBase"=dword:00000000
"Irq"=dword:ff
"IoLen"=dword:20
"DeviceArrayIndex"=dword:0
-------------------------------------------------------------------
BOOL WINAPI DllEntry(HANDLE hInstDll, DWORD dwReason, LPVOID lpvReserved)
{
switch ( dwReason )
{
case DLL_PROCESS_ATTACH:
DEBUGMSG(ZONE_INIT, (TEXT("BSD : DLL_PROCESS_ATTACH\r\n")));
DisableThreadLibraryCalls((HMODULE) hInstDll);
break;
case DLL_PROCESS_DETACH:
DEBUGMSG(ZONE_INIT, (TEXT("BSD : DLL_PROCESS_DETACH\r\n")));
break;
}
return (TRUE);
}
DWORD BSD_Init(DWORD dwInitParam)
{
RETAILMSG (1,(TEXT("+BSD_Init\r\n")));
//Start up the worker thread
g_hReadThread =
CreateThread(NULL,0,(LPTHREAD_START_ROUTINE)BsdReadThread,0,NULL);
if ( g_hReadThread == NULL )
{
RETAILMSG(1, (TEXT("Fatal Error! Failed to create BSD worker
thread.\r\n")));
return (FALSE);
}
}
RETAILMSG (1,(TEXT("BSD_Init: About to sleep\r\n")));
Sleep(10);
RETAILMSG (1,(TEXT("-BSD_Init\r\n")));
return (TRUE);
}
BOOL BSD_Deinit(DWORD dwData)
{
FUNC("+BSD_Deinit");
FUNC("-BSD_Deinit");
return (TRUE);
}
DWORD BSD_Open (DWORD dwData, DWORD dwAccess, DWORD dwShareMode) {return (4);}
BOOL BSD_Close(DWORD dwData) {return (TRUE);}
DWORD BSD_Read (DWORD dwData, LPVOID pBuf, DWORD Len) {return (0);}
DWORD BSD_Write(DWORD dwData, LPCVOID pBuf, DWORD Len) {return (0);}
DWORD BSD_Seek (DWORD dwData, long pos, DWORD type) {return (DWORD)-1;}
VOID BSD_PowerUp (VOID) {}
VOID BSD_PowerDown(VOID) {}
BOOL BSD_IOControl(DWORD p1, DWORD p2, PBYTE p3, DWORD p4, PBYTE p5, DWORD
p6, PDWORD p7) {return 0}
DWORD WINAPI BsdReadThread( LPVOID lpParameter)
{
HANDLE dummyEvent;
RETAILMSG (1,(TEXT("+BSD_ReadThread\r\n")));
while ( 1 )
{
Sleep(100);
RETAILMSG (1,(TEXT("BSD_ReadThread: Tick.\r\n")));
}
RETAILMSG( 1, (TEXT( "-BSD_ReadThread\r\n" )) );
return (1);
}
Is there something in the new CE 6.0 kernel model that I need to be aware of
relating to kernel drivers and this approach?
I have encountered this also. The working thread seems to end along with
the XXX_Init return.
There is another way that actually works is to use timer for this..I have
tested on WinCE60 and it works fine....here is the code example.
1. Mind the timer resolution, which is the 2nd parameter in the call to
"timeSetEvent", the smaller the accurate but it's a trade off between system
loading... usually, i set it to 1/10 of the sampling time (time interval for
your timer to enter to work).
2. Remember to have the lib link for use the timer --- Mmtimer.lib
typedef struct _DEVICE_INSTANCE {
LONG OpenCount; // Number of open handles.
CRITICAL_SECTION ControlMutex; // Access control for all
} DEVICE_INSTANCE, *PDEVICE_INSTANCE;
/******************************
* Run Timer
*******************************/
#define RUN_TIMER_PERIOD (60*1000) // 1 min in milliseconds
#define RUN_TIMER_RESOLUTION (RUN_TIMER_PERIOD/10) // take 1/10 of that of
RunTimer period
MMRESULT uRunTimerID = 0; // MMRESULT (equal to UINT or DWORD)
HINSTANCE g_hInstance;
CRITICAL_SECTION g_csControlMutex;
int StartRunTimer();
int StopRunTimer();
void CALLBACK RunTimerCallBack(UINT uID, UINT uMsg, DWORD_PTR dwUser,
DWORD_PTR dw1, DWORD_PTR dw2);
BOOL SCR_Deinit(IN OUT ULONG DeviceContext);
ULONG
SCR_Init(
IN ULONG RegistryPath
)
{
BOOL RoutineSuccess = FALSE;
PDEVICE_INSTANCE pDeviceInstance;
int nRet;
RETAILMSG(ZONE_INIT, (TEXT("SCR_Init(0x%x) entered.\r\n"), RegistryPath));
// Allocate a structure to hold the state for this instance. This value
// is used as a handle and is returned by this routine. When SMB_Open or
// SMB_Close is called, this handle will be passed in as a parameter.
//
pDeviceInstance = (PDEVICE_INSTANCE)LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT,
sizeof(*pDeviceInstance));
if (pDeviceInstance == NULL)
{
RETAILMSG(ZONE_INIT, (TEXT("SCR_Init: Failed to allocate device
instance.\r\n")));
goto ErrorReturn;
}
//
// Initialize the mutex to protect the device's Control register's shadow.
//
g_csControlMutex = pDeviceInstance->ControlMutex;
InitializeCriticalSection(&pDeviceInstance->ControlMutex);
//
// Initialize Run Timer
//
// Start Timer
nRet = StartRunTimer();
if (nRet != 1)
{
RETAILMSG(ZONE_INIT, (TEXT("SCR_Init: StartRunTimer
failed(Errcode=%d)\r\n"), nRet));
goto ErrorReturn;
}
}
RoutineSuccess = TRUE;
ErrorReturn:
//
// If the initialization failed, clean up and return a NULL to signal
// failure.
//
if (RoutineSuccess == FALSE)
{
SCR_Deinit((ULONG)pDeviceInstance);
pDeviceInstance = NULL;
}
RETAILMSG(ZONE_INIT && (pDeviceInstance == NULL), (TEXT("SCR_Init
failed.\r\n")));
return (ULONG)pDeviceInstance;
}
BOOL
SCR_Deinit(
IN OUT ULONG DeviceContext
)
{
PDEVICE_INSTANCE pDeviceInstance;
pDeviceInstance = (PDEVICE_INSTANCE)DeviceContext;
RETAILMSG(ZONE_INIT, (TEXT("SCR_Deinit(0x%x) entered.\r\n"),
DeviceContext));
//
// Depending on how things should be handled, we can look at the open
// count and see if there are still open handles to the device before
// shutting it down. It is possible to wait until the handles are closed,
// or just shut the device down. In this case, we just print a debug
// message if there are still open handles.
//
RETAILMSG(ZONE_INIT && (pDeviceInstance->OpenCount != 0), (
TEXT("SCR_Deinit: Handles still open. Shutting down anyway.\r\n")));
//
// Close the handle to the mutex protecting the device's control shadow.
//
DeleteCriticalSection(&pDeviceInstance->ControlMutex);
//
// Finally, the device instance itself can be freed.
//
LocalFree(pDeviceInstance);
RETAILMSG(ZONE_INIT, (TEXT("SCR_Deinit returning TRUE.\r\n")));
return TRUE;
}
int StartRunTimer()
{
DWORD dwUser = 0;
// If hourly timer does not start
if (!uRunTimerID)
{
// Start it now
uRunTimerID = timeSetEvent(RUN_TIMER_PERIOD, // Period of timer
RUN_TIMER_RESOLUTION, // Timer resolution
RunTimerCallBack, // Callback function
dwUser, // user callback data
TIME_PERIODIC);
if(uRunTimerID == 0)
{
return 0;
}
}
return 1;
}
int StopRunTimer()
{
if (uRunTimerID) // If hourly timer started
{
MMRESULT ret = timeKillEvent(uRunTimerID);
if (ret != TIMERR_NOERROR)
{
return 0;
}
uRunTimerID = 0; // release timer ID
}
return 1;
}
//=============================================================================
// Run Timer
//
void CALLBACK RunTimerCallBack(UINT uID, // Timer identifier
UINT uMsg, // Not currently used
DWORD_PTR dwUser, // User information
DWORD_PTR dw1, // Windows reserved
DWORD_PTR dw2) // is also reserved
{
EnterCriticalSection(&g_csControlMutex);
// do the working thread tasks here
LeaveCriticalSection(&g_csControlMutex);
--
Dean Ramsier - eMVP
BSQUARE Corporation
"tdacosta" <tdac...@discussions.microsoft.com> wrote in message
news:2B6E5494-4D0D-400D...@microsoft.com...