NTSTATUS Disk_GetPartitionLinkName(PWCHAR DriveLetter, WCHAR* pwchName, USHORT NameLen) { PDEVICE_OBJECT pDevice = NULL; PFILE_OBJECT pFileObject; NTSTATUS ntStatusRet = STATUS_UNSUCCESSFUL; UNICODE_STRING ObjectName; RtlInitUnicodeString(&ObjectName, DriveLetter); if (ObjectName.Length == sizeof(WCHAR)) { NTSTATUS ntStatus; HANDLE hDir; UNICODE_STRING us; OBJECT_ATTRIBUTES ObjAttr; HANDLE hLink; UNICODE_STRING targetNameUnicodeString; PFILE_OBJECT fileObject; IO_STATUS_BLOCK ioStatus; WCHAR cDrive[3] = L"A:"; RtlInitUnicodeString(&us, (PWCHAR)L"\\??"); InitializeObjectAttributes(&ObjAttr, &us, OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwOpenDirectoryObject(&hDir, DIRECTORY_QUERY,&ObjAttr); if(!NT_SUCCESS(ntStatus)) { DbPrint(DC_LLDISKIO, DL_ERROR, ("ZwOpenDirectoryObject %S failed, status %x\n",us.Buffer, ntStatus)); return ntStatusRet; } cDrive[0] = DriveLetter[0]; RtlInitUnicodeString(&us,cDrive); InitializeObjectAttributes(&ObjAttr, &us, OBJ_CASE_INSENSITIVE, hDir, NULL); ntStatus = ZwOpenSymbolicLinkObject(&hLink, SYMBOLIC_LINK_QUERY, &ObjAttr); if(NT_SUCCESS(ntStatus)) { RtlZeroMemory(pwchName, NameLen); targetNameUnicodeString.Buffer = pwchName; targetNameUnicodeString.MaximumLength = NameLen; ntStatus = ZwQuerySymbolicLinkObject(hLink, &targetNameUnicodeString, NULL); if(NT_SUCCESS(ntStatus)) { if(!wcsncmp(pwchName,L"\\Device",7)) ntStatusRet = STATUS_SUCCESS; } ZwClose(hLink); } ZwClose(hDir); } return ntStatusRet; }
BOOL GetWindowsRootName(WCHAR *WindowsRootName) { UNICODE_STRING RootName,ObjectName; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE hLink; NTSTATUS status; WCHAR *SystemRootName; WCHAR* ObjectNameBuffer; SystemRootName =(WCHAR*)0x7FFE0030; ObjectNameBuffer = (WCHAR*)ExAllocatePool(NonPagedPool,260*2); if (ObjectNameBuffer==NULL) { return FALSE; } RtlZeroMemory(ObjectNameBuffer,260*2); RtlInitUnicodeString(&RootName,L"\\SystemRoot"); InitializeObjectAttributes(&ObjectAttributes,&RootName,OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); status=ZwOpenSymbolicLinkObject(&hLink,1,&ObjectAttributes); if (NT_SUCCESS(status)) { ObjectName.Buffer=ObjectNameBuffer; ObjectName.Length=0; ObjectName.MaximumLength=260*2; status=ZwQuerySymbolicLinkObject(hLink,&ObjectName,NULL); if (NT_SUCCESS(status)) { int ObjectNameLength=ObjectName.Length/2; int Index; for (Index=ObjectNameLength-1;Index>0;Index--) { if (ObjectNameBuffer[Index]==0x005C) { if (!MmIsAddressValidEx(&WindowsRootName[ObjectNameLength-Index])) { break; } RtlCopyMemory(WindowsRootName,&ObjectNameBuffer[Index],(ObjectNameLength-Index)*2); ExFreePool(ObjectNameBuffer); return TRUE; } } } } ExFreePool(ObjectNameBuffer); if (!MmIsAddressValidEx(SystemRootName)) { return FALSE; } if (SystemRootName[1]!=0x003A||SystemRootName[2]!=0x005C) { return FALSE; } wcscpy(WindowsRootName,&SystemRootName[2]); return TRUE; }
NTSTATUS QuerySymbolicLink( IN PUNICODE_STRING SymbolicLinkName, OUT PUNICODE_STRING LinkTarget ) /*++ Routine Description: This routine returns the target of the symbolic link name. Arguments: SymbolicLinkName - Supplies the symbolic link name. LinkTarget - Returns the link target. Return Value: NTSTATUS --*/ { OBJECT_ATTRIBUTES oa; NTSTATUS status; HANDLE h; InitializeObjectAttributes(&oa, SymbolicLinkName, OBJ_CASE_INSENSITIVE, 0, 0); status = ZwOpenSymbolicLinkObject(&h, GENERIC_READ, &oa); if (!NT_SUCCESS(status)) { return status; } LinkTarget->MaximumLength = 200*sizeof(WCHAR); LinkTarget->Length = 0; LinkTarget->Buffer = ExAllocatePool(PagedPool, LinkTarget->MaximumLength); if (!LinkTarget->Buffer) { ZwClose(h); return STATUS_INSUFFICIENT_RESOURCES; } status = ZwQuerySymbolicLinkObject(h, LinkTarget, NULL); ZwClose(h); if (!NT_SUCCESS(status)) { ExFreePool(LinkTarget->Buffer); } return status; }
////////////////////////////////////////////////////////////////////////// // Function to get USB Root Hub device name, e.g., \Device\USBPDO-4 // NTSTATUS DkGetHubDevName(PIO_STACK_LOCATION pStack, PIRP pIrp, PULONG pUlRes) { NTSTATUS ntStat = STATUS_SUCCESS, clStat = STATUS_SUCCESS; HANDLE hObj; OBJECT_ATTRIBUTES oa; UNICODE_STRING usHubPath, usTgtDev; ULONG ulRet; RtlInitUnicodeString(&usHubPath, (PCWSTR) pIrp->AssociatedIrp.SystemBuffer); InitializeObjectAttributes(&oa, &usHubPath, OBJ_KERNEL_HANDLE, NULL, NULL); ntStat = ZwOpenSymbolicLinkObject(&hObj, GENERIC_ALL, &oa); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error open symbolic link!", ntStat); return ntStat; } usTgtDev.Length = 0; usTgtDev.MaximumLength = 512; usTgtDev.Buffer = (PWSTR) ExAllocatePoolWithTag(NonPagedPool, 512, DKPORT_MTAG); RtlFillMemory(usTgtDev.Buffer, 512, '\0'); ntStat = ZwQuerySymbolicLinkObject(hObj, &usTgtDev, &ulRet); if (!NT_SUCCESS(ntStat)) { DkDbgVal("Error query symbolic link!", ntStat); pIrp->IoStatus.Status = ntStat; *pUlRes = 0; } else { RtlFillMemory(pIrp->AssociatedIrp.SystemBuffer, pStack->Parameters.DeviceIoControl.InputBufferLength, '\0'); RtlCopyMemory(pIrp->AssociatedIrp.SystemBuffer, usTgtDev.Buffer, 512); pIrp->IoStatus.Information = usTgtDev.Length; pIrp->IoStatus.Status = ntStat; *pUlRes = (ULONG) usTgtDev.Length; } ExFreePoolWithTag(usTgtDev.Buffer, DKPORT_MTAG); clStat = ZwClose(hObj); if (!NT_SUCCESS(clStat)) { DkDbgVal("Error close symbolic link!", clStat); } return ntStat; }
/* * @implemented */ NTSTATUS MountMgrQuerySymbolicLink(IN PUNICODE_STRING SymbolicName, IN OUT PUNICODE_STRING LinkTarget) { NTSTATUS Status; HANDLE LinkHandle; OBJECT_ATTRIBUTES ObjectAttributes; /* Open the symbolic link */ InitializeObjectAttributes(&ObjectAttributes, SymbolicName, OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenSymbolicLinkObject(&LinkHandle, GENERIC_READ, &ObjectAttributes); if (!NT_SUCCESS(Status)) { return Status; } /* Query its target */ Status = ZwQuerySymbolicLinkObject(LinkHandle, LinkTarget, NULL); ZwClose(LinkHandle); if (!NT_SUCCESS(Status)) { return Status; } if (LinkTarget->Length <= sizeof(WCHAR)) { return Status; } /* If it's not finished by \, just return */ if (LinkTarget->Buffer[LinkTarget->Length / sizeof(WCHAR) - 1] != L'\\') { return Status; } /* Otherwise, ensure to drop the tailing \ */ LinkTarget->Length -= sizeof(WCHAR); LinkTarget->Buffer[LinkTarget->Length / sizeof(WCHAR)] = UNICODE_NULL; return Status; }
// ----------------------------------------------------------------------------------------- PDEVICE_OBJECT Disk_GetDeviceObjectByLetter(WCHAR DriveLetter) { PDEVICE_OBJECT pDevice = NULL; NTSTATUS ntStatus; HANDLE hDir; UNICODE_STRING us; OBJECT_ATTRIBUTES ObjAttr; HANDLE hLink; WCHAR targetNameBuffer[260]; UNICODE_STRING targetNameUnicodeString; PFILE_OBJECT fileObject; IO_STATUS_BLOCK ioStatus; WCHAR cDrive[3] = L"A:"; RtlInitUnicodeString(&us, (PWCHAR)L"\\??"); InitializeObjectAttributes(&ObjAttr, &us, OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus = ZwOpenDirectoryObject(&hDir, DIRECTORY_QUERY,&ObjAttr); if(!NT_SUCCESS(ntStatus)) { DbPrint(DC_LLDISKIO, DL_ERROR, ("ZwOpenDirectoryObject %S failed, status %x\n",us.Buffer, ntStatus)); return NULL; } cDrive[0] = DriveLetter; RtlInitUnicodeString(&us,cDrive); InitializeObjectAttributes(&ObjAttr, &us, OBJ_CASE_INSENSITIVE, hDir, NULL); ntStatus = ZwOpenSymbolicLinkObject(&hLink, SYMBOLIC_LINK_QUERY, &ObjAttr); if(NT_SUCCESS(ntStatus)) { RtlZeroMemory(targetNameBuffer, sizeof(targetNameBuffer)); targetNameUnicodeString.Buffer = targetNameBuffer; targetNameUnicodeString.MaximumLength = sizeof(targetNameBuffer); ntStatus = ZwQuerySymbolicLinkObject(hLink, &targetNameUnicodeString, NULL); if(NT_SUCCESS(ntStatus)) { if(!wcsncmp(targetNameBuffer,L"\\Device",7)) { HANDLE hFile; ntStatus = ZwCreateFile(&hFile, SYNCHRONIZE | FILE_ANY_ACCESS, &ObjAttr, &ioStatus, NULL, 0, FILE_SHARE_READ | FILE_SHARE_WRITE, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); if(NT_SUCCESS(ntStatus)) { //!FILE_DEVICE_MASS_STORAGE or FILE_DEVICE_TAPE ntStatus = ObReferenceObjectByHandle(hFile, FILE_READ_DATA, NULL, KernelMode, (PVOID*) &fileObject, NULL); if(NT_SUCCESS(ntStatus)) { pDevice = fileObject->DeviceObject; if (pDevice->Vpb != NULL) { if (pDevice->Vpb->RealDevice != NULL) pDevice = pDevice->Vpb->RealDevice; } if(pDevice->DeviceType == FILE_DEVICE_DISK || pDevice->DeviceType == FILE_DEVICE_CD_ROM || pDevice->DeviceType == FILE_DEVICE_DVD) { if(!NT_SUCCESS(ObReferenceObjectByPointer(pDevice, STANDARD_RIGHTS_REQUIRED, *IoDeviceObjectType, KernelMode))) //dereference will be in caller proc pDevice = NULL; } else pDevice = NULL; ObDereferenceObject(fileObject); } ZwClose(hFile); } } } ZwClose(hLink); } ZwClose(hDir); return pDevice; }
NTSTATUS FindHardDiskForPartition(PUNICODE_STRING pNameUnicodeString, PWCHAR pOutRequest, ULONG OutRequestSize, ULONG *pRetSize) { NTSTATUS ntRetStatus = STATUS_NOT_FOUND; NTSTATUS ntStatus; BYTE cou; OBJECT_ATTRIBUTES ObjAttr; HANDLE hDirectoryObject; BOOLEAN First; POBJECT_NAMETYPE_INFO p; HANDLE DrvHandle; PDRIVER_OBJECT pDrv; UNICODE_STRING Name; PWCHAR DrvName; PWCHAR DriverStr=L"Partition"; WCHAR Dir[128]; ULONG RegionSize; PMY_QUERY_DIRECTORY_STRUCT qds; qds = NULL; RegionSize = sizeof(MY_QUERY_DIRECTORY_STRUCT); if(!NT_SUCCESS(ntStatus = ZwAllocateVirtualMemory((HANDLE)-1, (PVOID*) &qds, 0, &RegionSize, // ^ - Whistler beta 2 doesn't work with 8 MEM_COMMIT,PAGE_READWRITE))) { DbPrint(DC_LLDISKIO, DL_ERROR,("ZwAllocateVirtualMemory fail. Status=%x\n", ntStatus)); } else { PWCHAR pdrvid; for(cou = 0; cou <= 9 && ntRetStatus != STATUS_SUCCESS; cou++) { wcscpy(Dir, L"\\Device\\Harddisk0"); pdrvid = &Dir[wcslen(Dir) - 1]; *(BYTE*)pdrvid += cou; RtlInitUnicodeString(&Name, Dir); InitializeObjectAttributes(&ObjAttr, &Name, OBJ_CASE_INSENSITIVE, NULL, NULL); ntStatus=ZwOpenDirectoryObject(&hDirectoryObject, DIRECTORY_QUERY, &ObjAttr); if(NT_SUCCESS(ntStatus)) { First=TRUE; DrvName=Dir+wcslen(Dir); *DrvName++='\\'; while(NtQueryDirectoryObject(hDirectoryObject, &qds->Buffer, QUERY_DIRECTORY_BUFF_SIZE, TRUE, First, &qds->Index, &qds->Retlen) >= 0 && ntRetStatus != STATUS_SUCCESS) { p=(POBJECT_NAMETYPE_INFO)&qds->Buffer; First=FALSE; *DrvName=0; if(wcsncmp(p->ObjectName.Buffer, DriverStr, 9)) continue; else { HANDLE hLink; InitializeObjectAttributes(&ObjAttr, &p->ObjectName, OBJ_CASE_INSENSITIVE, hDirectoryObject, NULL); ntStatus = ZwOpenSymbolicLinkObject(&hLink, SYMBOLIC_LINK_QUERY, &ObjAttr); if(NT_SUCCESS(ntStatus)) { WCHAR targetNameBuffer[260]; UNICODE_STRING targetNameUnicodeString; RtlZeroMemory(targetNameBuffer, sizeof(targetNameBuffer)); targetNameUnicodeString.Buffer = targetNameBuffer; targetNameUnicodeString.MaximumLength = sizeof(targetNameBuffer); ntStatus = ZwQuerySymbolicLinkObject(hLink, &targetNameUnicodeString, NULL); if(NT_SUCCESS(ntStatus) && (RtlCompareUnicodeString(&targetNameUnicodeString, pNameUnicodeString, FALSE) == 0)) { int number = GetHarddiskId(Dir); if (number != -1) { int cou2; int drvstrlen; char drstr[32]; sprintf(drstr, "%d", number); drvstrlen = strlen(drstr); wcscpy(pOutRequest, Dir); wcscat(pOutRequest, L"DR"); pdrvid = &pOutRequest[wcslen(pOutRequest) - 1] + 1; for (cou2 = 0; cou2 < drvstrlen; cou2++) { *pdrvid = (WCHAR) (drstr[cou2]); pdrvid++; } *pdrvid = 0; DbPrint(DC_LLDISKIO, DL_INFO, ("FindHardDiskForPartition found %S\n", pOutRequest)); *pRetSize = (wcslen(pOutRequest) + 1 ) * 2; ntRetStatus = STATUS_SUCCESS; } } ZwClose(hLink); } } } ZwClose(hDirectoryObject); } } } RegionSize = 0; _pfZwFreeVirtualMemory((HANDLE)-1,(PVOID*) &qds,&RegionSize,MEM_RELEASE); return ntRetStatus; }
NTSTATUS keyboardAddedOrRemoved(PVOID pNotification, PVOID pContext){ OBJECT_ATTRIBUTES symlinkAttr; UNICODE_STRING uSymlinkTarget; NTSTATUS status = STATUS_UNSUCCESSFUL; HANDLE hSymlink = INVALID_HANDLE_VALUE; ULONG maxTargetNameLength = 0; PWCHAR pTargetNameBuf = NULL; PDEVICE_INTERFACE_CHANGE_NOTIFICATION pChngNotification = (PDEVICE_INTERFACE_CHANGE_NOTIFICATION)pNotification; PDEVICE_OBJECT pKbdFnFltDev = (PDEVICE_OBJECT)pContext; //PDEVICE_OBJECT pKbdClassDev = NULL; if (!pChngNotification){ DbgPrint("pChngNotification = NULL!"); return STATUS_INVALID_PARAMETER; } if (!pKbdFnFltDev){ DbgPrint("pKbdFnFltDev = NULL!"); return STATUS_INVALID_PARAMETER; } if (!pKbdFnFltDev->DeviceExtension){ DbgPrint("pKbdFnFltDev->DeviceExtension = NULL!"); return STATUS_DRIVER_INTERNAL_ERROR; } if (!pChngNotification->SymbolicLinkName){ DbgPrint("pChngNotification->SymbolicLinkName = NULL!"); return STATUS_DRIVER_INTERNAL_ERROR; } //DbgPrint("Symlink name address: %p", pChngNotification->SymbolicLinkName); //DbgPrint("Symlink name: %wZ", *pChngNotification->SymbolicLinkName); //DbgPrint("size:%u", pChngNotification->Size); //((PKBDFNFLT_DEVICE_EXTENSION)(pKbdFnFltDev->DeviceExtension))->workContext.pItem = ((PKBDFNFLT_DEVICE_EXTENSION)(pKbdFnFltDev->DeviceExtension))->pWorkitem; //((PKBDFNFLT_DEVICE_EXTENSION)(pKbdFnFltDev->DeviceExtension))->workContext.pSymlink = pChngNotification->SymbolicLinkName; //IoQueueWorkItem(((PKBDFNFLT_DEVICE_EXTENSION)(pKbdFnFltDev->DeviceExtension))->pWorkitem, testRoutine, DelayedWorkQueue, &((PKBDFNFLT_DEVICE_EXTENSION)(pKbdFnFltDev->DeviceExtension))->workContext); //PFILE_OBJECT pFileObj = NULL; //PDEVICE_OBJECT pDevObj = NULL; ////FILE_READ_ATTRIBUTES //status = IoGetDeviceObjectPointer(pChngNotification->SymbolicLinkName, GENERIC_READ, &pFileObj, &pDevObj); //if (status) // DbgPrint("failed to access devobj!%lX", status); //OBJECT_TYPE //POBJECT_SYMBOLIC_LINK //LARGE_INTEGER interval; //OBJECT_DIRECTORY_INFORMATION //interval.QuadPart = -50000000; //KeDelayExecutionThread(KernelMode, FALSE, &interval); //POBJECT_SYMBOLIC_LINK pTestObj; //status = ObReferenceObjectByName(pChngNotification->SymbolicLinkName, // OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // NULL, 0, NULL, KernelMode, NULL, &pTestObj); ////IoGetR //if (status){ // DbgPrint("could not query object address%lX!", status); // return status; //} //ObfDereferenceObject(pTestObj); InitializeObjectAttributes(&symlinkAttr, pChngNotification->SymbolicLinkName, OBJ_KERNEL_HANDLE, NULL, NULL); status = ZwOpenSymbolicLinkObject(&hSymlink, GENERIC_READ, &symlinkAttr); if (status){ DbgPrint("Could not open symlink!%lX", status); return status; } //IoDriverObjectType //OBJECT_TYPE_LIST RtlInitUnicodeString(&uSymlinkTarget, L"\\"); maxTargetNameLength = 0; status = ZwQuerySymbolicLinkObject(hSymlink, &uSymlinkTarget, &maxTargetNameLength); if ((STATUS_BUFFER_TOO_SMALL != status) && status){ DbgPrint("Could not query symlink!%lX", status); ZwClose(hSymlink); return status; } pTargetNameBuf = ExAllocatePoolWithTag(NonPagedPool, maxTargetNameLength, g_poolTag); if (!pTargetNameBuf){ DbgPrint("Could not allocate pool for target name!"); ZwClose(hSymlink); return status; } RtlInitEmptyUnicodeString(&uSymlinkTarget, pTargetNameBuf, (USHORT)maxTargetNameLength); status = ZwQuerySymbolicLinkObject(hSymlink, &uSymlinkTarget, &maxTargetNameLength); if (status){ DbgPrint("NTSTATUS %lX", status); ExFreePoolWithTag(pTargetNameBuf, g_poolTag); ZwClose(hSymlink); return status; } //FILE_READ DbgPrint("Device: %wZ", uSymlinkTarget); //IoInitializeWorkItem //PIO_WORKITEM //IoGetDeviceObjectPointer(&uSymlinkTarget, GENERIC_READ, ) //KEYBOA //status = ObReferenceObjectByName(&uSymlinkTarget, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, // NULL, 0, IoDeviceObjectType, KernelMode, NULL, &pKbdClassDev); //ObReferenceObjectByName ExFreePoolWithTag(pTargetNameBuf, g_poolTag); ZwClose(hSymlink); //OBJECT_HEADER_NAME_INFO //if (status){ // DbgPrint("NTSTATUS %lX", status); // return status; //} //ObfDereferenceObject(pKbdClassDev); ////if (!status) //// //((PKBDFNFLT_DEVICE_EXTENSION)(pKbdFnFltDev->DeviceExtension))->pKeyboardDevice = pKbdClassDev; //// ObfDereferenceObject(pKbdClassDev); ////DbgPrint("NTSTATUS %lX", status); ////ExFreePoolWithTag(pTargetNameBuf, g_poolTag); ////ZwClose(hSymlink); //// return status; ////} // ////ObQueryNameString // //if (sizeof(GUID) == RtlCompareMemory(&GUID_DEVICE_INTERFACE_ARRIVAL, &pChngNotification->Event, sizeof(GUID))){ // DbgPrint("Device with symlink \"%wZ\" was attached/enabled.", *pChngNotification->SymbolicLinkName); // hookKeyboard((PDEVICE_OBJECT)pContext, (PDEVICE_OBJECT)pKbdClassDev); //}else if (sizeof(GUID) == RtlCompareMemory(&GUID_DEVICE_INTERFACE_REMOVAL, &pChngNotification->Event, sizeof(GUID))){ // DbgPrint("Device with symlink \"%wZ\" was removed.", *pChngNotification->SymbolicLinkName); // unhookKeyboard((PDEVICE_OBJECT)pContext, (PDEVICE_OBJECT)pKbdClassDev); //} ////else{ //// DbgPrint("Neither was a device removed nor was one attached."); ////} ////IoAttachDevice ///* //LARGE_INTEGER interval; //interval.QuadPart = -50000000; // //DbgPrint("device_name:%wZ", *pChngNotification->SymbolicLinkName); //KeDelayExecutionThread(KernelMode, FALSE, &interval);*/ return STATUS_SUCCESS; }
static VOID TestQueryLink( _In_ HANDLE LinkHandle, _In_ PCUNICODE_STRING ExpectedTarget) { NTSTATUS Status; WCHAR QueriedTargetBuffer[32]; UNICODE_STRING QueriedTarget; ULONG ResultLength; PULONG pResultLength; ULONG i; for (i = 0; i < 2; i++) { if (i == 0) { pResultLength = &ResultLength; } else { pResultLength = NULL; } /* Query with NULL Buffer just gives us the length */ RtlInitEmptyUnicodeString(&QueriedTarget, NULL, 0); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.MaximumLength, 0); ok_eq_pointer(QueriedTarget.Buffer, NULL); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); /* Query with Length-1 buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length - 1); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length - 1); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); /* Query with Length buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); if (pResultLength && QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength) { ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } /* Query with Length+1 buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length + 1); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + 1); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); if (pResultLength && QueriedTarget.MaximumLength < ExpectedTarget->MaximumLength) { ok_eq_hex(Status, STATUS_BUFFER_TOO_SMALL); ok_eq_uint(QueriedTarget.Length, 0); ok_eq_uint(QueriedTarget.Buffer[0], 0x5555); if (pResultLength) ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } /* Query with Length+2 buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, ExpectedTarget->Length + sizeof(WCHAR)); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok_eq_uint(QueriedTarget.MaximumLength, ExpectedTarget->Length + sizeof(WCHAR)); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); if (pResultLength) { if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL)) ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0); ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } /* Query with full-sized buffer */ RtlInitEmptyUnicodeString(&QueriedTarget, QueriedTargetBuffer, sizeof(QueriedTargetBuffer)); RtlFillMemory(&QueriedTargetBuffer, sizeof(QueriedTargetBuffer), 0x55); if (pResultLength) ResultLength = 0x55555555; Status = ZwQuerySymbolicLinkObject(LinkHandle, &QueriedTarget, pResultLength); ok_eq_hex(Status, STATUS_SUCCESS); ok_eq_uint(QueriedTarget.Length, ExpectedTarget->Length); ok_eq_uint(QueriedTarget.MaximumLength, sizeof(QueriedTargetBuffer)); ok_eq_pointer(QueriedTarget.Buffer, QueriedTargetBuffer); ok(RtlEqualUnicodeString(&QueriedTarget, ExpectedTarget, FALSE), "%wZ != %wZ\n", &QueriedTarget, ExpectedTarget); if (pResultLength) { if (ExpectedTarget->MaximumLength >= ExpectedTarget->Length + sizeof(UNICODE_NULL)) ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0); ok_eq_ulong(ResultLength, ExpectedTarget->MaximumLength); } else { ok_eq_uint(QueriedTarget.Buffer[QueriedTarget.Length / sizeof(WCHAR)], 0x5555); } } }
VOID NTAPI IopStoreSystemPartitionInformation(IN PUNICODE_STRING NtSystemPartitionDeviceName, IN PUNICODE_STRING OsLoaderPathName) { NTSTATUS Status; UNICODE_STRING LinkTarget, KeyName; OBJECT_ATTRIBUTES ObjectAttributes; HANDLE LinkHandle, RegistryHandle, KeyHandle; WCHAR LinkTargetBuffer[256]; UNICODE_STRING CmRegistryMachineSystemName = RTL_CONSTANT_STRING(L"\\Registry\\Machine\\SYSTEM"); ASSERT(NtSystemPartitionDeviceName->MaximumLength >= NtSystemPartitionDeviceName->Length + sizeof(WCHAR)); ASSERT(NtSystemPartitionDeviceName->Buffer[NtSystemPartitionDeviceName->Length / sizeof(WCHAR)] == UNICODE_NULL); ASSERT(OsLoaderPathName->MaximumLength >= OsLoaderPathName->Length + sizeof(WCHAR)); ASSERT(OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] == UNICODE_NULL); /* First define needed stuff to open NtSystemPartitionDeviceName symbolic link */ InitializeObjectAttributes(&ObjectAttributes, NtSystemPartitionDeviceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); /* Open NtSystemPartitionDeviceName symbolic link */ Status = ZwOpenSymbolicLinkObject(&LinkHandle, SYMBOLIC_LINK_QUERY, &ObjectAttributes); if (!NT_SUCCESS(Status)) { DPRINT("Failed to open symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status); return; } /* Prepare the string that will receive where symbolic link points to */ LinkTarget.Length = 0; /* We will zero the end of the string after having received it */ LinkTarget.MaximumLength = sizeof(LinkTargetBuffer) - sizeof(UNICODE_NULL); LinkTarget.Buffer = LinkTargetBuffer; /* Query target */ Status = ZwQuerySymbolicLinkObject(LinkHandle, &LinkTarget, NULL); /* We are done with symbolic link */ ObCloseHandle(LinkHandle, KernelMode); if (!NT_SUCCESS(Status)) { DPRINT("Failed querying symlink %wZ, Status=%lx\n", NtSystemPartitionDeviceName, Status); return; } /* As promised, we zero the end */ LinkTarget.Buffer[LinkTarget.Length / sizeof(WCHAR)] = UNICODE_NULL; /* Open registry to save data (HKLM\SYSTEM) */ Status = IopOpenRegistryKeyEx(&RegistryHandle, NULL, &CmRegistryMachineSystemName, KEY_ALL_ACCESS); if (!NT_SUCCESS(Status)) { DPRINT("Failed to open HKLM\\SYSTEM, Status=%lx\n", Status); return; } /* Open or create the Setup subkey where we'll store in */ RtlInitUnicodeString(&KeyName, L"Setup"); Status = IopCreateRegistryKeyEx(&KeyHandle, RegistryHandle, &KeyName, KEY_ALL_ACCESS, REG_OPTION_NON_VOLATILE, NULL); /* We're done with HKLM\SYSTEM */ ObCloseHandle(RegistryHandle, KernelMode); if (!NT_SUCCESS(Status)) { DPRINT("Failed opening/creating Setup key, Status=%lx\n", Status); return; } /* Prepare first data writing... */ RtlInitUnicodeString(&KeyName, L"SystemPartition"); /* Write SystemPartition value which is the target of the symbolic link */ Status = ZwSetValueKey(KeyHandle, &KeyName, 0, REG_SZ, LinkTarget.Buffer, LinkTarget.Length + sizeof(WCHAR)); if (!NT_SUCCESS(Status)) { DPRINT("Failed writing SystemPartition value, Status=%lx\n", Status); } /* Prepare for second data writing... */ RtlInitUnicodeString(&KeyName, L"OsLoaderPath"); /* Remove trailing slash if any (one slash only excepted) */ if (OsLoaderPathName->Length > sizeof(WCHAR) && OsLoaderPathName->Buffer[(OsLoaderPathName->Length / sizeof(WCHAR)) - 1] == OBJ_NAME_PATH_SEPARATOR) { OsLoaderPathName->Length -= sizeof(WCHAR); OsLoaderPathName->Buffer[OsLoaderPathName->Length / sizeof(WCHAR)] = UNICODE_NULL; } /* Then, write down data */ Status = ZwSetValueKey(KeyHandle, &KeyName, 0, REG_SZ, OsLoaderPathName->Buffer, OsLoaderPathName->Length + sizeof(UNICODE_NULL)); if (!NT_SUCCESS(Status)) { DPRINT("Failed writing OsLoaderPath value, Status=%lx\n", Status); } /* We're finally done! */ ObCloseHandle(KeyHandle, KernelMode); }
NTSTATUS HelloDDKRead(IN PDEVICE_OBJECT pDevObj, IN PIRP pIrp) { KdPrint(("DriverB:Enter B HelloDDKRead\n")); NTSTATUS ntStatus = STATUS_SUCCESS; UNICODE_STRING DeviceSymbolicLinkName; RtlInitUnicodeString( &DeviceSymbolicLinkName, L"\\??\\HelloDDKA" ); //初始化objectAttributes OBJECT_ATTRIBUTES objectAttributes; InitializeObjectAttributes(&objectAttributes, &DeviceSymbolicLinkName, OBJ_CASE_INSENSITIVE|OBJ_KERNEL_HANDLE, NULL, NULL ); HANDLE hSymbolic; //设定了FILE_SYNCHRONOUS_IO_NONALERT或者FILE_SYNCHRONOUS_IO_ALERT为同步打开设备 ntStatus = ZwOpenSymbolicLinkObject(&hSymbolic,FILE_ALL_ACCESS,&objectAttributes); #define UNICODE_SIZE 50 UNICODE_STRING LinkTarget; LinkTarget.Buffer = (PWSTR)ExAllocatePool(PagedPool,UNICODE_SIZE); LinkTarget.Length = 0; LinkTarget.MaximumLength = UNICODE_SIZE; ULONG unicode_length; ntStatus = ZwQuerySymbolicLinkObject(hSymbolic,&LinkTarget,&unicode_length); KdPrint(("DriverB:The device name is %wZ\n",&LinkTarget)); InitializeObjectAttributes(&objectAttributes, &LinkTarget, OBJ_CASE_INSENSITIVE, NULL, NULL ); HANDLE hDevice; IO_STATUS_BLOCK status_block; //设定了FILE_SYNCHRONOUS_IO_NONALERT或者FILE_SYNCHRONOUS_IO_ALERT为同步打开设备 ntStatus = ZwCreateFile(&hDevice, FILE_READ_ATTRIBUTES|SYNCHRONIZE, &objectAttributes, &status_block, NULL,FILE_ATTRIBUTE_NORMAL,FILE_SHARE_READ, FILE_OPEN_IF,FILE_SYNCHRONOUS_IO_NONALERT,NULL,0); if (NT_SUCCESS(ntStatus)) { ZwReadFile(hDevice,NULL,NULL,NULL,&status_block,NULL,0,NULL,NULL); } ZwClose(hDevice); ZwClose(hSymbolic); ExFreePool(LinkTarget.Buffer); ntStatus = STATUS_SUCCESS; // 完成IRP pIrp->IoStatus.Status = ntStatus; pIrp->IoStatus.Information = 0; // bytes xfered IoCompleteRequest( pIrp, IO_NO_INCREMENT ); KdPrint(("DriverB:Leave B HelloDDKRead\n")); return ntStatus; }
NTSTATUS ExtractFont(UINT32 CodePage, PUCHAR FontBitField) { BOOLEAN bFoundFile = FALSE; HANDLE Handle; NTSTATUS Status; CHAR FileName[20]; IO_STATUS_BLOCK IoStatusBlock; OBJECT_ATTRIBUTES ObjectAttributes; UNICODE_STRING LinkName; UNICODE_STRING SourceName; CFHEADER CabFileHeader; CFFILE CabFile; ULONG CabFileOffset = 0; LARGE_INTEGER ByteOffset; WCHAR SourceBuffer[MAX_PATH] = {L'\0'}; ULONG ReadCP; if(KeGetCurrentIrql() != PASSIVE_LEVEL) return STATUS_INVALID_DEVICE_STATE; RtlInitUnicodeString(&LinkName, L"\\SystemRoot"); InitializeObjectAttributes(&ObjectAttributes, &LinkName, OBJ_CASE_INSENSITIVE, NULL, NULL); Status = ZwOpenSymbolicLinkObject(&Handle, SYMBOLIC_LINK_ALL_ACCESS, &ObjectAttributes); if (!NT_SUCCESS(Status)) return(Status); SourceName.Length = 0; SourceName.MaximumLength = MAX_PATH * sizeof(WCHAR); SourceName.Buffer = SourceBuffer; Status = ZwQuerySymbolicLinkObject(Handle, &SourceName, NULL); ZwClose(Handle); Status = RtlAppendUnicodeToString(&SourceName, L"\\vgafonts.cab"); InitializeObjectAttributes(&ObjectAttributes, &SourceName, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL); Status = ZwCreateFile(&Handle, GENERIC_READ, &ObjectAttributes, &IoStatusBlock, NULL, FILE_ATTRIBUTE_NORMAL, 0, FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0); ByteOffset.LowPart = ByteOffset.HighPart = 0; if(NT_SUCCESS(Status)) { Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock, &CabFileHeader, sizeof(CabFileHeader), &ByteOffset, NULL); if(NT_SUCCESS(Status)) { if(CabFileHeader.Signature == CAB_SIGNATURE) { // We have a valid CAB file! // Read the file table now and decrement the file count on every file. When it's zero, we read the complete table. ByteOffset.LowPart = CabFileHeader.FileTableOffset; while(CabFileHeader.FileCount) { Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock, &CabFile, sizeof(CabFile), &ByteOffset, NULL); if(NT_SUCCESS(Status)) { ByteOffset.LowPart += sizeof(CabFile); // We assume here that the file name is max. 19 characters (+ 1 NULL character) long. // This should be enough for our purpose. Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock, FileName, sizeof(FileName), &ByteOffset, NULL); if(NT_SUCCESS(Status)) { if(!bFoundFile) { Status = RtlCharToInteger(FileName, 0, &ReadCP); if (NT_SUCCESS(Status) && ReadCP == CodePage) { // We got the correct file. // Save the offset and loop through the rest of the file table to find the position, where the actual data starts. CabFileOffset = CabFile.FileOffset; bFoundFile = TRUE; } } ByteOffset.LowPart += strlen(FileName) + 1; } } CabFileHeader.FileCount--; } // 8 = Size of a CFFOLDER structure (see cabman). As we don't need the values of that structure, just increase the offset here. ByteOffset.LowPart += 8; ByteOffset.LowPart += CabFileOffset; // ByteOffset now contains the offset of the actual data, so we can read the RAW font Status = ZwReadFile(Handle, NULL, NULL, NULL, &IoStatusBlock, FontBitField, 2048, &ByteOffset, NULL); ZwClose(Handle); return STATUS_SUCCESS; } else { DPRINT1("Error: CAB signature is missing!\n"); Status = STATUS_UNSUCCESSFUL; } } else DPRINT1("Error: Cannot read from file\n"); ZwClose(Handle); return Status; } else { DPRINT1("Error: Cannot open vgafonts.cab\n"); return Status; } }