static NTSTATUS FASTCALL BuildWindowStationNameList( ULONG dwSize, PVOID lpBuffer, PULONG pRequiredSize) { OBJECT_ATTRIBUTES ObjectAttributes; NTSTATUS Status; HANDLE DirectoryHandle; char InitialBuffer[256], *Buffer; ULONG Context, ReturnLength, BufferSize; DWORD EntryCount; POBJECT_DIRECTORY_INFORMATION DirEntry; WCHAR NullWchar; /* * Try to open the directory. */ InitializeObjectAttributes(&ObjectAttributes, &gustrWindowStationsDir, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwOpenDirectoryObject(&DirectoryHandle, DIRECTORY_QUERY, &ObjectAttributes); if (!NT_SUCCESS(Status)) { return Status; } /* First try to query the directory using a fixed-size buffer */ Context = 0; Buffer = NULL; Status = ZwQueryDirectoryObject(DirectoryHandle, InitialBuffer, sizeof(InitialBuffer), FALSE, TRUE, &Context, &ReturnLength); if (NT_SUCCESS(Status)) { if (STATUS_NO_MORE_ENTRIES == ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, FALSE, &Context, NULL)) { /* Our fixed-size buffer is large enough */ Buffer = InitialBuffer; } } if (NULL == Buffer) { /* Need a larger buffer, check how large exactly */ Status = ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, TRUE, &Context, &ReturnLength); if (!NT_SUCCESS(Status)) { ERR("ZwQueryDirectoryObject failed\n"); ZwClose(DirectoryHandle); return Status; } BufferSize = ReturnLength; Buffer = ExAllocatePoolWithTag(PagedPool, BufferSize, TAG_WINSTA); if (NULL == Buffer) { ZwClose(DirectoryHandle); return STATUS_NO_MEMORY; } /* We should have a sufficiently large buffer now */ Context = 0; Status = ZwQueryDirectoryObject(DirectoryHandle, Buffer, BufferSize, FALSE, TRUE, &Context, &ReturnLength); if (! NT_SUCCESS(Status) || STATUS_NO_MORE_ENTRIES != ZwQueryDirectoryObject(DirectoryHandle, NULL, 0, FALSE, FALSE, &Context, NULL)) { /* Something went wrong, maybe someone added a directory entry? Just give up. */ ExFreePoolWithTag(Buffer, TAG_WINSTA); ZwClose(DirectoryHandle); return NT_SUCCESS(Status) ? STATUS_INTERNAL_ERROR : Status; } } ZwClose(DirectoryHandle); /* * Count the required size of buffer. */ ReturnLength = sizeof(DWORD); EntryCount = 0; for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length; DirEntry++) { ReturnLength += DirEntry->Name.Length + sizeof(WCHAR); EntryCount++; } TRACE("Required size: %lu Entry count: %lu\n", ReturnLength, EntryCount); if (NULL != pRequiredSize) { Status = MmCopyToCaller(pRequiredSize, &ReturnLength, sizeof(ULONG)); if (! NT_SUCCESS(Status)) { if (Buffer != InitialBuffer) { ExFreePoolWithTag(Buffer, TAG_WINSTA); } return STATUS_BUFFER_TOO_SMALL; } } /* * Check if the supplied buffer is large enough. */ if (dwSize < ReturnLength) { if (Buffer != InitialBuffer) { ExFreePoolWithTag(Buffer, TAG_WINSTA); } return STATUS_BUFFER_TOO_SMALL; } /* * Generate the resulting buffer contents. */ Status = MmCopyToCaller(lpBuffer, &EntryCount, sizeof(DWORD)); if (! NT_SUCCESS(Status)) { if (Buffer != InitialBuffer) { ExFreePoolWithTag(Buffer, TAG_WINSTA); } return Status; } lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(DWORD)); NullWchar = L'\0'; for (DirEntry = (POBJECT_DIRECTORY_INFORMATION) Buffer; 0 != DirEntry->Name.Length; DirEntry++) { Status = MmCopyToCaller(lpBuffer, DirEntry->Name.Buffer, DirEntry->Name.Length); if (! NT_SUCCESS(Status)) { if (Buffer != InitialBuffer) { ExFreePoolWithTag(Buffer, TAG_WINSTA); } return Status; } lpBuffer = (PVOID) ((PCHAR) lpBuffer + DirEntry->Name.Length); Status = MmCopyToCaller(lpBuffer, &NullWchar, sizeof(WCHAR)); if (! NT_SUCCESS(Status)) { if (Buffer != InitialBuffer) { ExFreePoolWithTag(Buffer, TAG_WINSTA); } return Status; } lpBuffer = (PVOID) ((PCHAR) lpBuffer + sizeof(WCHAR)); } /* * Clean up */ if (Buffer != InitialBuffer) { ExFreePoolWithTag(Buffer, TAG_WINSTA); } return STATUS_SUCCESS; }
void STDCALL look_for_vols(PDRIVER_OBJECT DriverObject, LIST_ENTRY* volumes) { PFILE_OBJECT FileObject; PDEVICE_OBJECT mountmgr; OBJECT_ATTRIBUTES attr; UNICODE_STRING mmdevpath, us; HANDLE h; OBJECT_DIRECTORY_INFORMATION* odi; ULONG odisize; ULONG context; BOOL restart; NTSTATUS Status; LIST_ENTRY* le; static const WCHAR directory[] = L"Directory"; static const WCHAR harddisk[] = L"Harddisk"; RtlInitUnicodeString(&mmdevpath, MOUNTMGR_DEVICE_NAME); Status = IoGetDeviceObjectPointer(&mmdevpath, FILE_READ_ATTRIBUTES, &FileObject, &mountmgr); if (!NT_SUCCESS(Status)) { ERR("IoGetDeviceObjectPointer returned %08x\n", Status); return; } RtlInitUnicodeString(&us, devpath); attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.ObjectName = &us; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; Status = ZwOpenDirectoryObject(&h, DIRECTORY_TRAVERSE, &attr); if (!NT_SUCCESS(Status)) { ERR("ZwOpenDirectoryObject returned %08x\n", Status); return; } odisize = sizeof(OBJECT_DIRECTORY_INFORMATION) * 16; odi = ExAllocatePoolWithTag(PagedPool, odisize, ALLOC_TAG); if (!odi) { ERR("out of memory\n"); ZwClose(h); return; } restart = TRUE; do { Status = ZwQueryDirectoryObject(h, odi, odisize, FALSE, restart, &context, NULL/*&retlen*/); restart = FALSE; if (!NT_SUCCESS(Status)) { if (Status != STATUS_NO_MORE_ENTRIES) ERR("ZwQueryDirectoryObject returned %08x\n", Status); } else { OBJECT_DIRECTORY_INFORMATION* odi2 = odi; while (odi2->Name.Buffer) { if (odi2->TypeName.Length == wcslen(directory) * sizeof(WCHAR) && RtlCompareMemory(odi2->TypeName.Buffer, directory, odi2->TypeName.Length) == odi2->TypeName.Length && odi2->Name.Length > wcslen(harddisk) * sizeof(WCHAR) && RtlCompareMemory(odi2->Name.Buffer, harddisk, wcslen(harddisk) * sizeof(WCHAR)) == wcslen(harddisk) * sizeof(WCHAR)) { look_in_harddisk_dir(DriverObject, mountmgr, &odi2->Name, volumes); } odi2 = &odi2[1]; } } } while (NT_SUCCESS(Status)); ExFreePool(odi); ZwClose(h); le = volumes->Flink; while (le != volumes) { volume* v = CONTAINING_RECORD(le, volume, list_entry); if (!v->processed) { LIST_ENTRY* le2 = le; volume* mountvol = v; while (le2 != volumes) { volume* v2 = CONTAINING_RECORD(le2, volume, list_entry); if (RtlCompareMemory(&v2->fsuuid, &v->fsuuid, sizeof(BTRFS_UUID)) == sizeof(BTRFS_UUID)) { v2->processed = TRUE; if (v2->devnum < mountvol->devnum) { remove_drive_letter(mountmgr, mountvol); mountvol = v2; } else if (v2->devnum > mountvol->devnum) remove_drive_letter(mountmgr, v2); } le2 = le2->Flink; } add_volume(mountmgr, &mountvol->devpath); } le = le->Flink; } ObDereferenceObject(FileObject); }
NTSTATUS Mouse_Hook(IN PDRIVER_OBJECT driverObject) { ULONG i; int found = 1; NTSTATUS status = STATUS_SUCCESS; PIO_STACK_LOCATION stack; UNICODE_STRING uniMouseDeviceName; PFILE_OBJECT mouseFileObject; PDEVICE_OBJECT MouseDeviceObject; ULONG counter; HANDLE hDir; OBJECT_ATTRIBUTES oa; UNICODE_STRING uniOa; PVOID pBuffer; PVOID pContext; ULONG RetLen; PDIRECTORY_BASIC_INFORMATION pDirBasicInfo; UNICODE_STRING uniMouseDrv; char* mouseclsNum; char arMouseCls[0x10]; WCHAR tmpNameBuffer[512]; DbgPrint("Running Mouse_Create."); RtlInitUnicodeString(&uniOa, L"\\Device"); InitializeObjectAttributes( &oa,&uniOa, OBJ_CASE_INSENSITIVE,NULL,NULL); status = ZwOpenDirectoryObject( &hDir,DIRECTORY_ALL_ACCESS,&oa); if(!NT_SUCCESS(status)) return status; pBuffer = ExAllocatePool(PagedPool, ALLOC_SIZE); pContext = ExAllocatePool(PagedPool, ALLOC_SIZE); // pBuffer = ExAllocatePoolWithTag(PagedPool, ALLOC_SIZE, Tag); // pContext = ExAllocatePoolWithTag(PagedPool, ALLOC_SIZE, Tag); memset(pBuffer, 0, ALLOC_SIZE); memset(pContext, 0, ALLOC_SIZE); memset(arMouseCls, 0, 0x10); counter = 0; g_Mouseclsnum = 0; while(TRUE) { status = ZwQueryDirectoryObject(hDir,pBuffer,ALLOC_SIZE,TRUE,FALSE,pContext,&RetLen); if(!NT_SUCCESS(status)) break; pDirBasicInfo = (PDIRECTORY_BASIC_INFORMATION)pBuffer; pDirBasicInfo->ObjectName.Length -= 2; RtlInitUnicodeString(&uniMouseDrv, L"PointerClass"); if(RtlCompareUnicodeString( &pDirBasicInfo->ObjectName, &uniMouseDrv,FALSE) == 0){ mouId = (ULONG)(*(char *)(pDirBasicInfo->ObjectName.Buffer+pDirBasicInfo->ObjectName.Length)); mouId -= 0x30; pDirBasicInfo->ObjectName.Length += 2; RtlInitUnicodeString(&uniMouseDeviceName, pDirBasicInfo->ObjectName.Buffer); found = 1; break; } pDirBasicInfo->ObjectName.Length += 2; } ExFreePool(pBuffer); ExFreePool(pContext); ZwClose(hDir); if( found == 0 ) return status; DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"Mouse_Hook ----> mouId[%d].\n", mouId); swprintf(tmpNameBuffer, L"\\Device\\%s", uniMouseDeviceName.Buffer); RtlInitUnicodeString(&uniMouseDeviceName, tmpNameBuffer); status = My_IoGetDeviceObjectPointer(&uniMouseDeviceName, FILE_ALL_ACCESS, &mouseFileObject,&MouseDeviceObject); if(NT_SUCCESS(status)) { g_MouseDeviceObject = MouseDeviceObject; ObDereferenceObject(mouseFileObject); g_OldReadFunction = g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_READ]; g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_READ] = Mouse_HookProc; g_OldInternalDeviceFunction = g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]; g_MouseDeviceObject->DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL] = Mouse_IO_InternalIoctl; DbgPrintEx( DPFLTR_IHVDRIVER_ID, DPFLTR_INFO_LEVEL,"Mouse_Create ----> Mouse_HookProc success.\n"); } return status; }
static NTSTATUS look_in_harddisk_dir(PDRIVER_OBJECT DriverObject, PDEVICE_OBJECT mountmgr, PUNICODE_STRING name, LIST_ENTRY* volumes) { UNICODE_STRING path; OBJECT_ATTRIBUTES attr; NTSTATUS Status; HANDLE h; OBJECT_DIRECTORY_INFORMATION* odi; ULONG odisize, context; BOOL restart, has_part0 = FALSE, has_parts = FALSE; static const WCHAR partition[] = L"Partition"; static WCHAR partition0[] = L"Partition0"; path.Buffer = ExAllocatePoolWithTag(PagedPool, ((wcslen(devpath) + 1) * sizeof(WCHAR)) + name->Length, ALLOC_TAG); if (!path.Buffer) { ERR("out of memory\n"); return STATUS_INSUFFICIENT_RESOURCES; } RtlCopyMemory(path.Buffer, devpath, wcslen(devpath) * sizeof(WCHAR)); path.Buffer[wcslen(devpath)] = '\\'; RtlCopyMemory(&path.Buffer[wcslen(devpath) + 1], name->Buffer, name->Length); path.Length = path.MaximumLength = ((wcslen(devpath) + 1) * sizeof(WCHAR)) + name->Length; attr.Length = sizeof(attr); attr.RootDirectory = 0; attr.Attributes = OBJ_CASE_INSENSITIVE; attr.ObjectName = &path; attr.SecurityDescriptor = NULL; attr.SecurityQualityOfService = NULL; Status = ZwOpenDirectoryObject(&h, DIRECTORY_TRAVERSE, &attr); if (!NT_SUCCESS(Status)) { ERR("ZwOpenDirectoryObject returned %08x\n", Status); goto end; } odisize = sizeof(OBJECT_DIRECTORY_INFORMATION) * 16; odi = ExAllocatePoolWithTag(PagedPool, odisize, ALLOC_TAG); if (!odi) { ERR("out of memory\n"); Status = STATUS_INSUFFICIENT_RESOURCES; ZwClose(h); goto end; } restart = TRUE; do { Status = ZwQueryDirectoryObject(h, odi, odisize, FALSE, restart, &context, NULL/*&retlen*/); restart = FALSE; if (!NT_SUCCESS(Status)) { if (Status != STATUS_NO_MORE_ENTRIES) ERR("ZwQueryDirectoryObject returned %08x\n", Status); } else { OBJECT_DIRECTORY_INFORMATION* odi2 = odi; while (odi2->Name.Buffer) { TRACE("%.*S, %.*S\n", odi2->TypeName.Length / sizeof(WCHAR), odi2->TypeName.Buffer, odi2->Name.Length / sizeof(WCHAR), odi2->Name.Buffer); if (odi2->Name.Length > wcslen(partition) * sizeof(WCHAR) && RtlCompareMemory(odi2->Name.Buffer, partition, wcslen(partition) * sizeof(WCHAR)) == wcslen(partition) * sizeof(WCHAR)) { if (odi2->Name.Length == (wcslen(partition) + 1) * sizeof(WCHAR) && odi2->Name.Buffer[(odi2->Name.Length / sizeof(WCHAR)) - 1] == '0') { // Partition0 refers to the whole disk has_part0 = TRUE; } else { has_parts = TRUE; test_vol(DriverObject, mountmgr, &path, &odi2->Name, FALSE, volumes); } } odi2 = &odi2[1]; } } } while (NT_SUCCESS(Status)); // If disk had no partitions, test the whole disk if (!has_parts && has_part0) { UNICODE_STRING part0us; part0us.Buffer = partition0; part0us.Length = part0us.MaximumLength = wcslen(partition0) * sizeof(WCHAR); test_vol(DriverObject, mountmgr, &path, &part0us, TRUE, volumes); } ZwClose(h); ExFreePool(odi); Status = STATUS_SUCCESS; end: ExFreePool(path.Buffer); return Status; }