Hi,
I am trying to write an unloadable driver, to achieve that I have created a
minimal, presumably unloadable driver, Loading and initializing the driver
succeeds BUT unloading ( using 'ControlService(SERVICE_CONTROL_STOP)' ) fails
with the following error: "The requested control is not valid for this
service.", What may cause such an error? I have added the required
DeviceCreate and DeviceClose ICTL Handlers but it had no effectâ?¦
// The CreateClose IOCTL I have added...
NTSTATUS DispatchCreateClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information=0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
Any help, pointers or samples would be appreciatedâ?¦
Following is the short code with which I am experiancing the problem:
The Driver:
**********
#pragma code_seg("INIT")
// This handler is NEVER called...
VOID __stdcall Unload(IN PDRIVER_OBJECT DriverObject) {
UNICODE_STRING uszDeviceString;
DbgPrint("Simple C++ Driver - Unload.\n");
IoDeleteDevice(DriverObject->DeviceObject);
RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\ProcDrv");
IoDeleteSymbolicLink(&uszDeviceString);
TerminateCppRunTime();
}
NTSTATUS __stdcall DriverEntry(IN PDRIVER_OBJECT DriverObject
, IN PUNICODE_STRING
RegistryPath) {
DbgPrint("Simple C++ Driver - DriverEntry\nCompiled at " __TIME__ "
on " __DATE__ "\n");
NTSTATUS Status = InitializeCppRunTime();
if (STATUS_SUCCESS != Status)
goto ErrorExit;
UNICODE_STRING uszDriverString, uszDeviceString;
RtlInitUnicodeString(&uszDriverString, L"\\Device\\ProcDrv");
RtlInitUnicodeString(&uszDeviceString, L"\\DosDevices\\ProcDrv");
DbgPrint("C++ runtime was initialized successfuly...\n");
PDEVICE_OBJECT pDeviceObject = NULL;
Status = IoCreateDevice(DriverObject, 0, &uszDriverString,
FILE_DEVICE_UNKNOWN, 0, FALSE,
&pDeviceObject);
if (STATUS_SUCCESS != Status)
goto ErrorExit;
DbgPrint("Device created successfuly...\n");
Status = IoCreateSymbolicLink(&uszDeviceString, &uszDriverString);
if(Status != STATUS_SUCCESS) {
Unload(DriverObject);
goto ErrorExit;
}
DbgPrint("Link created successfuly...\n");
DriverObject->DriverUnload = Unload;
goto SafeExit;
ErrorExit:
TerminateCppRunTime();
SafeExit:
DbgPrint("DriverEntry retruns 0x%.8x\n", Status);
return Status;
}
#pragma code_seg()
The driver Loading/Unloading routine
*******************************
BOOL WaitForState(SC_HANDLE hDriver,
DWORD dwDesiredState,
SERVICE_STATUS* pss) {
while (1) {
if(FALSE == ::QueryServiceStatus(hDriver, pss))
return FALSE;
// If the driver reaches the desired state
if (pss->dwCurrentState == dwDesiredState)
break;
DWORD dwWaitHint = pss->dwWaitHint / 10;
if (dwWaitHint < 1000) dwWaitHint = 1000; // At most once a second
if (dwWaitHint > 10000) dwWaitHint = 10000; // At least every 10 seconds
::Sleep(dwWaitHint);
} // while
return TRUE;
}
int _tmain(int argc, _TCHAR* argv[]) {
// Start the driver
SC_HANDLE hSCM = ::OpenSCManager(NULL, NULL,
SC_MANAGER_ALL_ACCESS);
SC_HANDLE hDriver= ::CreateService(hSCM, "ProcDrv", "ProcDrv",
SERVICE_ALL_ACCESS,
SERVICE_KERNEL_DRIVER,
SERVICE_DEMAND_START,
SERVICE_ERROR_NORMAL,
argv[1], NULL,
NULL, NULL,
NULL, NULL);
if(0 == hDriver && (::GetLastError() == ERROR_SERVICE_EXISTS ||
::GetLastError() == ERROR_SERVICE_MARKED_FOR_DELETE) &&
(0 == (hDriver = ::OpenService(hSCM, "ProcDrv", SERVICE_ALL_ACCESS))))
return 0;
SERVICE_STATUS serviceStatus = { 0 };
BOOL bResult = ::StartService(hDriver, 0, NULL);
if (bResult)
bResult = WaitForState(hDriver, SERVICE_RUNNING, &serviceStatus);
else
bResult = (::GetLastError() == ERROR_SERVICE_ALREADY_RUNNING);
if (!bResult) {
::DeleteService(hDriver);
::CloseServiceHandle(hDriver);
} else {
// Stop the driver, returns "The requested control is not valid for this
service."
if(TRUE == (bResult = ::ControlService(hDriver,
SERVICE_CONTROL_STOP,
&serviceStatus)))
bResult = WaitForState(hDriver, SERVICE_STOPPED, &serviceStatus);
::DeleteService(hDriver);
::CloseServiceHandle(hDriver);
}
::CloseServiceHandle(hSCM);
return 0;
}
Nadav.
http://www.sophin.com