I have a kernel driver that enum and close all handles (of type "File") of files present in a specific folder, and this is the code of reference about how start to this goal. The kernel code is works very fine, but i have a small problem more specifically on moment to stop the driver. Then when execute the usermode code below STOP_PENDING is all that happens, and i'm not able close the usermode program. Already when i not execute the kernel code (to close handles), the driver can be stopped and deleted with success.
PS: The usermode code not open any handle to target folder.
Some idea about reason to this strange behavior?
To better understanding here in this forum, i will post only relevant codes usermode/kernel mode.
Usermode:
function UninstallService(sMachine, sService: string): Boolean;
var
schm, schs: SC_Handle;
ss: TServiceStatus;
dwChkP: dword;
begin
Result := False;
schm := OpenSCManagerW(PWideChar(sMachine), nil, SC_MANAGER_CONNECT);
if schm > 0 then
begin
schs := OpenServiceW(schm, PWideChar(sService), _DELETE or SERVICE_STOP or SERVICE_QUERY_STATUS);
if schs > 0 then
begin
if (QueryServiceStatus(schs, ss)) then
begin
while (SERVICE_STOPPED <> ss.dwCurrentState) do
begin
ControlService(schs, SERVICE_CONTROL_STOP, ss);
dwChkP := ss.dwCheckPoint;
Sleep(ss.dwWaitHint);
if (not QueryServiceStatus(schs, ss)) then
Break;
if (ss.dwCheckPoint < dwChkP) then
Break;
end;
end;
Result := DeleteService(schs);
CloseServiceHandle(schs);
end;
CloseServiceHandle(schm);
schm := OpenSCManagerW(PWideChar(sMachine), nil, SC_MANAGER_CONNECT);
if schm > 0 then
begin
schs := OpenServiceW(schm, PWideChar(sService), _DELETE or SERVICE_STOP or SERVICE_QUERY_STATUS);
if schs = 0 then
begin
if GetLastError = ERROR_SERVICE_DOES_NOT_EXIST then
begin
Writeln('Service not exists');
Result := True;
end;
end
else
begin
CloseServiceHandle(schs);
end;
CloseServiceHandle(schm);
end;
end;
end;
Kernel code:
NTSTATUS DrvProcCreate(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
NTSTATUS DrvProcClose(IN PDEVICE_OBJECT DeviceObject, IN PIRP Irp)
{
Irp->IoStatus.Status = STATUS_SUCCESS;
Irp->IoStatus.Information = 0;
IoCompleteRequest(Irp, IO_NO_INCREMENT);
return STATUS_SUCCESS;
}
#define NT_DEVICE_NAME L"\\Device\\MyDrv"
#define DOS_DEVICE_NAME L"\\??\\MyDrv"
void DrvProcUnload(IN PDRIVER_OBJECT DriverObject)
{
UNICODE_STRING deviceLinkUnicodeString;
NTSTATUS status;
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);
status = IoDeleteSymbolicLink(&deviceLinkUnicodeString);
if (!NT_SUCCESS(status))
{
DbgPrint("IoDeleteSymbolicLink() error - 0x%X \n", status);
return;
}
IoDeleteDevice(DriverObject->DeviceObject);
DbgPrint("Goodbye from driver \n");
}
NTSTATUS DriverEntry(IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
UNICODE_STRING deviceNameUnicodeString;
UNICODE_STRING deviceLinkUnicodeString;
PDEVICE_OBJECT deviceObject = NULL;
NTSTATUS ntStatus = STATUS_SUCCESS;
RtlInitUnicodeString(&deviceNameUnicodeString, NT_DEVICE_NAME);
ntStatus = IoCreateDevice(DriverObject, 0, &deviceNameUnicodeString, FILE_DEVICE_UNKNOWN, FILE_DEVICE_SECURE_OPEN, FALSE, &deviceObject);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("IoCreateDevice() error - 0x%X \n", ntStatus);
return ntStatus;
}
RtlInitUnicodeString(&deviceLinkUnicodeString, DOS_DEVICE_NAME);
ntStatus = IoCreateSymbolicLink(&deviceLinkUnicodeString, &deviceNameUnicodeString);
if (!NT_SUCCESS(ntStatus))
{
DbgPrint("IoCreateSymbolicLink() error - 0x%X \n", ntStatus);
if (NULL != deviceObject)
{
IoDeleteDevice(deviceObject);
}
return ntStatus;
}
DriverObject->MajorFunction[IRP_MJ_CREATE] = DrvProcCreate;
DriverObject->DriverUnload = DrvProcUnload;
DriverObject->MajorFunction[IRP_MJ_CLOSE] = DrvProcClose;
DbgPrint("Hello from driver \n");
return ntStatus;
}
Edit:
After first comment below, ControlService returns:
1061 - ERROR_SERVICE_CANNOT_ACCEPT_CTRL, but in docs:
Drivers do not accept control codes other than SERVICE_CONTROL_STOP and SERVICE_CONTROL_INTERROGATE.
Edit 2:
I tried unload with PC Hunter ARK (a famous chinese anti rootkit) and my driver was stopped with success. The implementation of PC Hunter to unload .sys module is something like this. Why with Win32 api (ring3 - usermode) not works, someone know explain?