Exemple #1
0
NTSTATUS CreateDevice (IN PDRIVER_OBJECT pDriverObject) 
{
	KdPrint(("CreateDevice begin\n"));

	NTSTATUS status;
	//设备对象 指针
	PDEVICE_OBJECT pDevObj;
	//设备对象扩展结构 指针
	PDEVICE_EXTENSION pDevExt;
	
	//设备名称
	UNICODE_STRING devName;
	RtlInitUnicodeString(&devName,DRIVER_NAME);
	
	//创建设备
	status = IoCreateDevice( pDriverObject,			//驱动对象
						sizeof(DEVICE_EXTENSION),	//设备扩展结构大小
						&(UNICODE_STRING)devName,	//设备名 或 NULL
						FILE_DEVICE_UNKNOWN,		//设备类型 FILE_DEVICE_UNKNOWN 未知虚拟设备,且为独占(既只能被一个应用程序使用) 
						0, TRUE,
						&pDevObj );					//设备地址 out

	if (!NT_SUCCESS(status))
		return status;

	//以直接的方式读写(既不使用缓冲区)
	pDevObj->Flags |= DO_DIRECT_IO;

	//填充扩展结构数据
	pDevExt = (PDEVICE_EXTENSION)pDevObj->DeviceExtension;
	pDevExt->pDevice = pDevObj;
	//申请内存 保存设备名
	ULONG length=wcslen(DRIVER_NAME)*sizeof(WCHAR);
	pDevExt->ustrDeviceName.Buffer=(PWCH)ExAllocatePool(PagedPool,length);
	pDevExt->ustrDeviceName.Length=pDevExt->ustrDeviceName.MaximumLength=length;
	RtlCopyUnicodeString(&pDevExt->ustrDeviceName,&devName);
	
	//符号链接名
	UNICODE_STRING symLinkName;
	RtlInitUnicodeString(&symLinkName,DRIVER_LINK_NAME);
	
	//创建符号链接
	pDevExt->ustrSymLinkName = symLinkName;
	status = IoCreateSymbolicLink( &symLinkName,&devName );
	
	if (!NT_SUCCESS(status)) 
	{
		IoDeleteDevice( pDevObj );
		return status;
	}
	//申请内存 保存 符号链接名
	length=wcslen(DRIVER_LINK_NAME)*sizeof(WCHAR);
	pDevExt->ustrSymLinkName.Buffer=(PWCH)ExAllocatePool(PagedPool,length);
	pDevExt->ustrSymLinkName.Length=pDevExt->ustrSymLinkName.MaximumLength=length;
	RtlCopyUnicodeString(&pDevExt->ustrSymLinkName,&symLinkName);
	
	KdPrint(("CreateDevice sucess and end\n"));
	return STATUS_SUCCESS;
}
Exemple #2
0
VOID
KdbSymProcessSymbols(
    IN PLDR_DATA_TABLE_ENTRY LdrEntry)
{
    if (!LoadSymbols)
    {
        LdrEntry->PatchInformation = NULL;
        return;
    }

    /* Remove symbol info if it already exists */
    if (LdrEntry->PatchInformation) {
        KdbpSymRemoveCachedFile(LdrEntry->PatchInformation);
    }

	/* Error loading symbol info, try to load it from file */
	KdbpSymLoadModuleSymbols(&LdrEntry->FullDllName,
            (PROSSYM_INFO*)&LdrEntry->PatchInformation);

    if (!LdrEntry->PatchInformation) {
        // HACK: module dll names don't identify the real files
        UNICODE_STRING SystemRoot;
        UNICODE_STRING ModuleNameCopy;
        RtlInitUnicodeString(&SystemRoot, L"\\SystemRoot\\System32\\Drivers\\");
        ModuleNameCopy.Length = 0;
        ModuleNameCopy.MaximumLength =
            LdrEntry->BaseDllName.MaximumLength + SystemRoot.MaximumLength;
        ModuleNameCopy.Buffer = ExAllocatePool(NonPagedPool, SystemRoot.MaximumLength + LdrEntry->BaseDllName.MaximumLength);
        RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
        RtlCopyMemory
            (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
             LdrEntry->BaseDllName.Buffer,
             LdrEntry->BaseDllName.Length);
        ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
        KdbpSymLoadModuleSymbols(&ModuleNameCopy,
                                 (PROSSYM_INFO*)&LdrEntry->PatchInformation);
        if (!LdrEntry->PatchInformation) {
            SystemRoot.Length -= strlen("Drivers\\") * sizeof(WCHAR);
            RtlCopyUnicodeString(&ModuleNameCopy, &SystemRoot);
            RtlCopyMemory
                (ModuleNameCopy.Buffer + ModuleNameCopy.Length / sizeof(WCHAR),
                 LdrEntry->BaseDllName.Buffer,
                 LdrEntry->BaseDllName.Length);
            ModuleNameCopy.Length += LdrEntry->BaseDllName.Length;
            KdbpSymLoadModuleSymbols(&ModuleNameCopy,
                                     (PROSSYM_INFO*)&LdrEntry->PatchInformation);
        }
        RtlFreeUnicodeString(&ModuleNameCopy);
    }

	/* It already added symbols to cache */
    DPRINT("Installed symbols: %wZ@%p-%p %p\n",
           &LdrEntry->BaseDllName,
           LdrEntry->DllBase,
           (PVOID)(LdrEntry->SizeOfImage + (ULONG_PTR)LdrEntry->DllBase),
           LdrEntry->PatchInformation);
}
Exemple #3
0
NTSTATUS DriverEntry(__in PDRIVER_OBJECT DriverObject, __in PUNICODE_STRING RegistryPath)
{
    Bus_KdPrint(("Driver Entry\n"));

    ExInitializeNPagedLookasideList(&g_LookAside, NULL, NULL, 0, sizeof(PENDING_IRP), BUSENUM_POOL_TAG, 0);

	Globals.RegistryPath.MaximumLength = RegistryPath->Length + sizeof(UNICODE_NULL);
    Globals.RegistryPath.Length = RegistryPath->Length;
    Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(PagedPool, Globals.RegistryPath.MaximumLength, BUSENUM_POOL_TAG);

    if (!Globals.RegistryPath.Buffer)
	{
		return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);

    DriverObject->MajorFunction [IRP_MJ_CREATE                 ] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE                  ] = Bus_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_PNP                    ] = Bus_PnP;
    DriverObject->MajorFunction [IRP_MJ_POWER                  ] = Bus_Power;
    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL         ] = Bus_IoCtl;
    DriverObject->MajorFunction [IRP_MJ_INTERNAL_DEVICE_CONTROL] = Bus_Internal_IoCtl;

	DriverObject->DriverUnload = Bus_DriverUnload;
    DriverObject->DriverExtension->AddDevice = Bus_AddDevice;

    return STATUS_SUCCESS;
}
Exemple #4
0
/*! \brief Add a symbol file to the cache.
 *
 * \param FileName    Filename of the symbol file.
 * \param RosSymInfo  Pointer to the symbol info.
 *
 * \sa KdbpSymRemoveCachedFile
 */
static VOID
KdbpSymAddCachedFile(
    IN PUNICODE_STRING FileName,
    IN PROSSYM_INFO RosSymInfo)
{
    PIMAGE_SYMBOL_INFO_CACHE CacheEntry;
    KIRQL Irql;

    DPRINT("Adding symbol file: RosSymInfo = %p\n", RosSymInfo);

    /* allocate entry */
    CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
    ASSERT(CacheEntry);
    RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));

    /* fill entry */
    CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
                                                        FileName->Length,
                                                        TAG_KDBS);
    RtlCopyUnicodeString(&CacheEntry->FileName, FileName);
    ASSERT(CacheEntry->FileName.Buffer);
    CacheEntry->RefCount = 1;
    CacheEntry->RosSymInfo = RosSymInfo;
    KeAcquireSpinLock(&SymbolFileListLock, &Irql);
    InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry);
    KeReleaseSpinLock(&SymbolFileListLock, Irql);
}
Exemple #5
0
/*! \brief Add a symbol file to the cache.
 *
 * \param FileName    Filename of the symbol file.
 * \param RosSymInfo  Pointer to the symbol info.
 *
 * \sa KdbpSymRemoveCachedFile
 */
static VOID
KdbpSymAddCachedFile(
    IN PUNICODE_STRING FileName,
    IN PROSSYM_INFO RosSymInfo)
{
    PIMAGE_SYMBOL_INFO_CACHE CacheEntry;

    DPRINT("Adding symbol file: %wZ RosSymInfo = %p\n", FileName, RosSymInfo);

    /* allocate entry */
    CacheEntry = ExAllocatePoolWithTag(NonPagedPool, sizeof (IMAGE_SYMBOL_INFO_CACHE), TAG_KDBS);
    ASSERT(CacheEntry);
    RtlZeroMemory(CacheEntry, sizeof (IMAGE_SYMBOL_INFO_CACHE));

    /* fill entry */
    CacheEntry->FileName.Buffer = ExAllocatePoolWithTag(NonPagedPool,
                                                        FileName->Length,
                                                        TAG_KDBS);
    CacheEntry->FileName.MaximumLength = FileName->Length;
    RtlCopyUnicodeString(&CacheEntry->FileName, FileName);
    ASSERT(CacheEntry->FileName.Buffer);
    CacheEntry->RefCount = 1;
    CacheEntry->RosSymInfo = RosSymInfo;
    InsertTailList(&SymbolFileListHead, &CacheEntry->ListEntry); /* FIXME: Lock list? */
}
Exemple #6
0
NTSTATUS
ConstructDeviceName(
    IN  PCWSTR Path,
    IN  UCHAR Index,
    OUT PUNICODE_STRING DeviceName)
{
    UNICODE_STRING UnicodePath;
    UNICODE_STRING UnicodeIndex;
    WCHAR IndexStringBuffer[5];
    USHORT Size;
    USHORT LastCharacterIndex;

    /* Check for NULL parameters */
    if ( ( ! Path ) || ( ! DeviceName ) )
    {
        DPRINT("Unexpected NULL parameter");
        return STATUS_INVALID_PARAMETER;
    }

    /* Range-check */
    if ( Index >= SOUND_MAX_DEVICES )
    {
        DPRINT("Device index %d out of range", Index);
        return STATUS_INVALID_PARAMETER;
    }

    /* Initialise the unicode path string */
    RtlInitUnicodeString(&UnicodePath, Path);

    /* Calculate the length to hold the full string */
    Size = UnicodePath.Length +
           sizeof(IndexStringBuffer) +
           sizeof(UNICODE_NULL);

    /* Allocate memory for DeviceName */
    DeviceName->Buffer = ExAllocatePool(PagedPool, Size);
    DeviceName->MaximumLength = Size;

    if ( ! DeviceName->Buffer )
    {
        DPRINT("Couldn't allocate memory for device name string");
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Copy the path */
    RtlCopyUnicodeString(DeviceName, &UnicodePath);

    /* Convert Index to string and append */
    UnicodeIndex.Buffer = IndexStringBuffer;
    UnicodeIndex.MaximumLength = sizeof(IndexStringBuffer);

    RtlIntegerToUnicodeString((ULONG)Index, 10, &UnicodeIndex);
    RtlAppendUnicodeStringToString(DeviceName, &UnicodeIndex);

    /* Terminate the string */
    LastCharacterIndex = DeviceName->Length / sizeof(UNICODE_NULL);
    DeviceName->Buffer[LastCharacterIndex] = UNICODE_NULL;

    return STATUS_SUCCESS;
}
/*++

Routine Description:

    This routine updates the name of the target in the supplied stream handle context

Arguments:

    DirectoryName             - Supplies the directory name
    StreamHandleContext   - Returns the updated name in the stream context

Return Value:

    Status

Note:

    The caller must synchronize access to the context. This routine does no
    synchronization

--*/
NTSTATUS
CtxUpdateNameInStreamHandleContext (
    __in PUNICODE_STRING DirectoryName,
    __inout PCTX_STREAMHANDLE_CONTEXT StreamHandleContext
    )
{
    NTSTATUS status;

    PAGED_CODE();

    //
    //  Free any existing name
    //

    if (StreamHandleContext->FileName.Buffer != NULL) 
	{
        CtxFreeUnicodeString(&StreamHandleContext->FileName);
    }


    //
    //  Allocate and copy off the directory name
    //

    StreamHandleContext->FileName.MaximumLength = DirectoryName->Length;
    status = CtxAllocateUnicodeString(&StreamHandleContext->FileName);
    if (NT_SUCCESS(status))
	{
        RtlCopyUnicodeString(&StreamHandleContext->FileName, DirectoryName);
    }

    return status;
}
Exemple #8
0
VOID
Secondary_ChangeFcbFileName(
	IN PIRP_CONTEXT		IrpContext,
	IN PFCB				Fcb,
	IN PUNICODE_STRING	FullFileName
	)
{
    RtlInitEmptyUnicodeString( &Fcb->FullFileName,
							   Fcb->FullFileNameBuffer,
							   sizeof(Fcb->FullFileNameBuffer) );

	RtlCopyUnicodeString( &Fcb->FullFileName, FullFileName );

    RtlInitEmptyUnicodeString( &Fcb->CaseInSensitiveFullFileName,
							   Fcb->CaseInSensitiveFullFileNameBuffer,
							   sizeof(Fcb->CaseInSensitiveFullFileNameBuffer) );

	RtlDowncaseUnicodeString( &Fcb->CaseInSensitiveFullFileName,
							  &Fcb->FullFileName,
							  FALSE );

	if (FullFileName->Length && FullFileName->Buffer[0] != L'\\')
		ASSERT( NDFAT_BUG );

	return;
}
Exemple #9
0
NTSTATUS
DriverEntry (
    __in  PDRIVER_OBJECT  DriverObject,
    __in  PUNICODE_STRING RegistryPath
    )
/*++
Routine Description:

    Initialize the driver dispatch table.

Arguments:

    DriverObject - pointer to the driver object

    RegistryPath - pointer to a unicode string representing the path,
                   to driver-specific key in the registry.

Return Value:

  NT Status Code

--*/
{

    Bus_KdPrint_Def (BUS_DBG_SS_TRACE, ("Driver Entry \n"));

    //
    // Save the RegistryPath for WMI.
    //

    Globals.RegistryPath.MaximumLength = RegistryPath->Length +
                                          sizeof(UNICODE_NULL);
    Globals.RegistryPath.Length = RegistryPath->Length;
    Globals.RegistryPath.Buffer = ExAllocatePoolWithTag(
                                       PagedPool,
                                       Globals.RegistryPath.MaximumLength,
                                       BUSENUM_POOL_TAG
                                       );

    if (!Globals.RegistryPath.Buffer) {

        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyUnicodeString(&Globals.RegistryPath, RegistryPath);

    //
    // Set entry points into the driver
    //
    DriverObject->MajorFunction [IRP_MJ_CREATE] =
    DriverObject->MajorFunction [IRP_MJ_CLOSE] = Bus_CreateClose;
    DriverObject->MajorFunction [IRP_MJ_PNP] = Bus_PnP;
    DriverObject->MajorFunction [IRP_MJ_POWER] = Bus_Power;
    DriverObject->MajorFunction [IRP_MJ_DEVICE_CONTROL] = Bus_IoCtl;
    DriverObject->MajorFunction[IRP_MJ_SYSTEM_CONTROL] = Bus_SystemControl;
    DriverObject->DriverUnload = Bus_DriverUnload;
    DriverObject->DriverExtension->AddDevice = Bus_AddDevice;

    return STATUS_SUCCESS;
}
Exemple #10
0
NTSTATUS
_NewVolumeEntry(
	_Out_ PVOLUME_ENTRY *VolumeEntry,
	_In_ PCUNICODE_STRING DosName,
	_In_ PCUNICODE_STRING DeviceName
)
{
	PVOLUME_ENTRY newEntry = NULL;
	NTSTATUS      status   = STATUS_SUCCESS;

	if (VolumeEntry == NULL) {
		DBG_ERROR("VolumeEntry cannot be null.\n");
		status = STATUS_INVALID_PARAMETER;
		goto Exit;
	}
	
	newEntry = (PVOLUME_ENTRY)MirAllocatePagedPool(sizeof(VOLUME_ENTRY));
	if (newEntry == NULL) {
		DBG_ERROR_ALLOC_FAIL(newEntry, sizeof(VOLUME_ENTRY));
		goto Exit;
	}

	InitializeListHead(&newEntry->MirrorList.ListHead);
	
	status = MirAllocateUnicodeString(&newEntry->DosName, DosName->Length);
	if (!NT_SUCCESS(status)) {
		DBG_ERROR_ALLOC_FAIL(newEntry->DosName, DosName->Length);
		MirFreePool(newEntry);
		goto Exit;
	}
	status = MirAllocateUnicodeString(&newEntry->DeviceName, DeviceName->Length);
	if (!NT_SUCCESS(status)) {
		DBG_ERROR_ALLOC_FAIL(newEntry->DeviceName, DeviceName->Length);
		MirFreeUnicodeString(&newEntry->DosName);
		MirFreePool(newEntry);
		goto Exit;
	}

	RtlCopyUnicodeString(&newEntry->DosName, DosName);
	RtlCopyUnicodeString(&newEntry->DeviceName, DeviceName);

	*VolumeEntry = newEntry;

Exit:
	return status;
}
Exemple #11
0
// 
// 实现我们自己的AddDevice函数
//
NTSTATUS myAddDevice(
					 IN PDRIVER_OBJECT  DriverObject,
					 IN PDEVICE_OBJECT  PhysicalDeviceObject 
					 )
{
	if(gDeviceObject != NULL)
	{
		// 在这里面创建我们自己的设备对象,或者申请所需要的资源。
		// 为了区分不同实例,将设备对象名构造成:”MyNdisDevice”+HardwareID。
		UNICODE_STRING nameString; 
		WCHAR wcsName[256];
		UNICODE_STRING preName = RTL_CONSTANT_STRING(L"\\Device\\MyNdisDevice");

		// 首先取得设备的HDID。
		ULONG nameLength = 0;
		WCHAR wcsHardwareID[256]; //足够大了
		NTSTATUS status = IoGetDeviceProperty (PhysicalDeviceObject,
			DevicePropertyHardwareID,
			256,
			wcsHardwareID,
			&nameLength);
		if(status != STATUS_SUCCESS){
			KdPrint(("Failed to get hardware ID %x\n", status));
			return status;
		}

		// 下面构造设备对象的名字,根据上面的规则:“MyNdisDevice”+ HardwareID。
		RtlInitEmptyUnicodeString( &nameString, wcsName, 256*2);
		RtlCopyUnicodeString( &nameString, &preName);
		//RtlUnicodeStringPrintf(&nameString, L"%wZ_%d_", &preName, 0);
		RtlAppendUnicodeToString( &nameString, wcsHardwareID);

		status = IoCreateDevice(DriverObject,
			0,
			&nameString,
			FILE_DEVICE_UNKNOWN,
			FILE_DEVICE_SECURE_OPEN,
			FALSE,
			&gDeviceObject); 

		// 如果创建失败了,我们有权利让函数以失败返回
		// 但这样我们的驱动加载也就失败了
		if(status != STATUS_SUCCESS){
			KdPrint(("Failed to create device %ws\n", nameString));
			return status;
		}
	}

	//ExAllocatePoolWithTag(); //申请资源及其他

	// 
	// 还可以加入其他正确的操作
	//

	// 现在调用保存的Ndis库中的AddDevice实现
	// 千万不要忘记,否则就会大错特错了
	return systemAddDevice(DriverObject, PhysicalDeviceObject);
}
Exemple #12
0
NTSTATUS
FltpGetObjectName(_In_ PVOID Object,
                  _Inout_ PUNICODE_STRING ObjectName)
{
    POBJECT_NAME_INFORMATION ObjectNameInfo = NULL;
    OBJECT_NAME_INFORMATION LocalNameInfo;
    ULONG ReturnLength;
    NTSTATUS Status;

    if (ObjectName == NULL)
        return STATUS_INVALID_PARAMETER;

    /* Get the size of the buffer required to hold the nameinfo */
    Status = ObQueryNameString(Object,
                              &LocalNameInfo,
                              sizeof(LocalNameInfo),
                              &ReturnLength);
    if (Status == STATUS_INFO_LENGTH_MISMATCH)
    {
        ObjectNameInfo = ExAllocatePoolWithTag(PagedPool,
                                               ReturnLength,
                                               FM_TAG_UNICODE_STRING);
        if (ObjectNameInfo == NULL) return STATUS_INSUFFICIENT_RESOURCES;

        /* Get the actual name info now we have the buffer to hold it */
        Status = ObQueryNameString(Object,
                                    ObjectNameInfo,
                                    ReturnLength,
                                    &ReturnLength);
    }


    if (NT_SUCCESS(Status))
    {
        /* Make sure the buffer we were passed is large enough to hold the string */
        if (ObjectName->MaximumLength < ObjectNameInfo->Name.Length)
        {
            /* It wasn't, let's enlarge the buffer */
            Status = FltpReallocateUnicodeString(ObjectName,
                                                 ObjectNameInfo->Name.Length,
                                                 FALSE);
            
        }

        if (NT_SUCCESS(Status))
        {
            /* Copy the object name into the callers buffer */
            RtlCopyUnicodeString(ObjectName, &ObjectNameInfo->Name);
        }
    }

    if (ObjectNameInfo)
    {
        ExFreePoolWithTag(ObjectNameInfo, FM_TAG_UNICODE_STRING);
    }

    return Status;
}
Exemple #13
0
HDC
APIENTRY
NtGdiOpenDCW(
    PUNICODE_STRING pustrDevice,
    DEVMODEW *pdmInit,
    PUNICODE_STRING pustrLogAddr,
    ULONG iType,
    BOOL bDisplay,
    HANDLE hspool,
    VOID *pDriverInfo2,
    VOID *pUMdhpdev)
{
    UNICODE_STRING ustrDevice;
    WCHAR awcDevice[CCHDEVICENAME];
    DEVMODEW dmInit;
    PVOID dhpdev;
    HDC hdc;

    /* Only if a devicename is given, we need any data */
    if (pustrDevice)
    {
        /* Initialize destination string */
        RtlInitEmptyUnicodeString(&ustrDevice, awcDevice, sizeof(awcDevice));

        _SEH2_TRY
        {
            /* Probe the UNICODE_STRING and the buffer */
            ProbeForRead(pustrDevice, sizeof(UNICODE_STRING), 1);
            ProbeForRead(pustrDevice->Buffer, pustrDevice->Length, 1);

            /* Copy the string */
            RtlCopyUnicodeString(&ustrDevice, pustrDevice);

            if (pdmInit)
            {
                /* FIXME: could be larger */
                ProbeForRead(pdmInit, sizeof(DEVMODEW), 1);
                RtlCopyMemory(&dmInit, pdmInit, sizeof(DEVMODEW));
            }

            if (pUMdhpdev)
            {
                ProbeForWrite(pUMdhpdev, sizeof(HANDLE), 1);
            }
        }
        _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
        {
            SetLastNtError(_SEH2_GetExceptionCode());
            _SEH2_YIELD(return NULL);
        }
        _SEH2_END
    }
    else
    {
Exemple #14
0
PUNICODE_STRING CopyUS(PUNICODE_STRING a)
{
    PUNICODE_STRING b = (PUNICODE_STRING)ExAllocatePool(PagedPool,sizeof(UNICODE_STRING));
    ok(b != NULL, "US is NULL after allocated memory\n");
    b->Length = 0;
    b->MaximumLength =a->MaximumLength;
    b->Buffer = (PWSTR)ExAllocatePoolWithTag(PagedPool, b->MaximumLength, 1633);
    ok(b->Buffer != NULL, "US->Buffer is NULL after allocated memory\n");
    RtlCopyUnicodeString(b, a);
    return b;
}
Exemple #15
0
NTSTATUS
CtxUpdateNameInStreamHandleContext (
    __in PUNICODE_STRING DirectoryName,
    __inout PCTX_STREAMHANDLE_CONTEXT StreamHandleContext
    )
/*++

Routine Description:

    This routine updates the name of the target in the supplied stream handle context

Arguments:

    DirectoryName             - Supplies the directory name
    StreamHandleContext   - Returns the updated name in the stream context

Return Value:

    Status

Note:

    The caller must synchronize access to the context. This routine does no
    synchronization

--*/
{
    NTSTATUS status;

    PAGED_CODE();

    //
    //  Free any existing name
    //

    if (StreamHandleContext->FileName.Buffer != NULL) {

        CtxFreeUnicodeString(&StreamHandleContext->FileName);
    }


    //
    //  Allocate and copy off the directory name
    //

    StreamHandleContext->FileName.MaximumLength = DirectoryName->Length;
    status = CtxAllocateUnicodeString(&StreamHandleContext->FileName);
    if (NT_SUCCESS(status)) {

        RtlCopyUnicodeString(&StreamHandleContext->FileName, DirectoryName);
    }

    return status;
}
Exemple #16
0
NTSTATUS
Ctx_UpdateNameInStreamContext (
    __in PUNICODE_STRING DirectoryName,
    __inout PSTREAM_CONTEXT StreamContext
    )
/*++

Routine Description:

    This routine updates the name of the target in the supplied stream context

Arguments:

    DirectoryName         - Supplies the directory name
    StreamContext    - Returns the updated name in the stream context

Return Value:

    Status

Note:

    The caller must synchronize access to the context. This routine does no
    synchronization

--*/
{
    NTSTATUS status = STATUS_SUCCESS ;

    PAGED_CODE();

    //Free any existing name
	if (StreamContext->FileName.Buffer != NULL) 
	{
		ExFreePoolWithTag( StreamContext->FileName.Buffer,STRING_TAG );

		StreamContext->FileName.Length = StreamContext->FileName.MaximumLength = 0;
		StreamContext->FileName.Buffer = NULL;
	}

    //Allocate and copy off the directory name
    StreamContext->FileName.MaximumLength = DirectoryName->Length;
    StreamContext->FileName.Buffer = ExAllocatePoolWithTag( PagedPool,
                                            StreamContext->FileName.MaximumLength,
                                            STRING_TAG );
    if (StreamContext->FileName.Buffer == NULL) 
	{
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyUnicodeString(&StreamContext->FileName, DirectoryName);

    return status;
}
Exemple #17
0
NTSTATUS DriverEntry (IN PDRIVER_OBJECT DriverObject, IN PUNICODE_STRING RegistryPath)
{
 NTSTATUS	ntStatus;
 
 ntStatus= STATUS_SUCCESS;
 PPJoyBus_DebugLevel= PPJOY_DEFAULT_DEBUGLEVEL;

 PPJOY_DBGPRINT (FILE_PPJOYBUS|PPJOY_WARN, ("Built " __DATE__ " at " __TIME__) );
 PPJOY_DBGPRINT (FILE_PPJOYBUS|PPJOY_FENTRY, ("DriverEntry (DriverObject=0x%p,RegistryPath=0x%p)",DriverObject, RegistryPath) );

 RtlZeroMemory (&Globals,sizeof(Globals));

 /* Setup copy of DriverObject first so we can use it for event log function */
 Globals.DriverObject= DriverObject;

 /* Allocate buffer to store registry path to the parameters registry key */
 Globals.ParamRegistryPath.MaximumLength= RegistryPath->Length+sizeof(UNICODE_NULL)+sizeof(PARAM_KEY_NAME);
 Globals.ParamRegistryPath.Length= RegistryPath->Length;
 Globals.ParamRegistryPath.Buffer= ExAllocatePoolWithTag (PagedPool,Globals.ParamRegistryPath.MaximumLength,PPJOYBUS_POOL_TAG);    

 if (!Globals.ParamRegistryPath.Buffer)
 {
  PPJoyBus_WriteEventLog (PPJ_MSG_ERRORALLOCMEM,&ntStatus,sizeof(ntStatus),L"");
  ntStatus= STATUS_INSUFFICIENT_RESOURCES;
  goto Exit;
 }

 /* Copy driver registry path and append the parameters subkey name */
 RtlCopyUnicodeString (&Globals.ParamRegistryPath,RegistryPath);
 RtlAppendUnicodeToString (&Globals.ParamRegistryPath,PARAM_KEY_NAME);

 ExInitializeFastMutex (&Globals.Mutex);

 PPJOY_DBGPRINT (FILE_PPJOYBUS|PPJOY_BABBLE2, ("ParamRegistryPath=%S",Globals.ParamRegistryPath.Buffer) );

 /* Set up pointers to our other entry points in the DeviceObject */
 DriverObject->MajorFunction[IRP_MJ_CREATE]= PPJoyBus_CreateClose;
 DriverObject->MajorFunction[IRP_MJ_CLOSE]=	PPJoyBus_CreateClose;
 DriverObject->MajorFunction[IRP_MJ_POWER]= PPJoyBus_Power;
 DriverObject->MajorFunction[IRP_MJ_PNP]= PPJoyBus_PnP;
 DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL]= PPJoyBus_Ioctl;
 DriverObject->MajorFunction[IRP_MJ_INTERNAL_DEVICE_CONTROL]= PPJoyBus_InternalIoctl;
 DriverObject->DriverUnload= PPJoyBus_Unload;
 DriverObject->DriverExtension->AddDevice= PPJoyBus_AddDevice;

 PPJoyBus_WriteEventLog (PPJ_MSG_DRIVERSTARTEDVER,&ntStatus,sizeof(ntStatus),LVER_PRODUCTVERSION_STR);

Exit:
 PPJOY_EXITPROC (FILE_PPJOYBUS|PPJOY_FEXIT_STATUSOK , "DriverEntry", ntStatus);

 return ntStatus;
} /* DriverEntry */
Exemple #18
0
/****************************************************************************\
 *
 * NT_DupUnicodeString()
 *
 * DESCRIPTION:
 *
 *  Allocates a copy of UNICODE string
 *
 * ARGUMENTS:
 *
 *  String - string to duplicate
 *  MaxLen - max length of the new string, in characters. If zero, allocates
             just enough to copy the contents of the source
 *
 * RETURN VALUE:
 *
 *  Pointer to the new string, NULL if memory allocation failed
 *
\****************************************************************************/
PUNICODE_STRING 
NT_DupUnicodeString(IN PUNICODE_STRING String, IN USHORT MaxLen)
{
    PUNICODE_STRING NewString = NULL;
    ASSERT(String);
    if (String) {
        USHORT ActualMaxLength = MAX(MaxLen, String->Length/sizeof(WCHAR));
        NewString = NT_AllocUnicodeString(ActualMaxLength);
        if (NewString) {
            RtlCopyUnicodeString( NewString, String);
        }
    }
    return (NewString);
}
Exemple #19
0
static
BOOL
LDEVOBJ_bLoadImage(
    _Inout_ PLDEVOBJ pldev,
    _In_ PUNICODE_STRING pustrPathName)
{
    PSYSTEM_GDI_DRIVER_INFORMATION pDriverInfo;
    NTSTATUS Status;
    ULONG cbSize;

    /* Make sure no image is loaded yet */
    ASSERT(pldev && pldev->pGdiDriverInfo == NULL);

    /* Allocate a SYSTEM_GDI_DRIVER_INFORMATION structure */
    cbSize = sizeof(SYSTEM_GDI_DRIVER_INFORMATION) + pustrPathName->Length;
    pDriverInfo = ExAllocatePoolWithTag(PagedPool, cbSize, GDITAG_LDEV);
    if (!pDriverInfo)
    {
        ERR("Failed to allocate SYSTEM_GDI_DRIVER_INFORMATION\n");
        return FALSE;
    }

    /* Initialize the UNICODE_STRING and copy the driver name */
    RtlInitEmptyUnicodeString(&pDriverInfo->DriverName,
                              (PWSTR)(pDriverInfo + 1),
                              pustrPathName->Length);
    RtlCopyUnicodeString(&pDriverInfo->DriverName, pustrPathName);

    /* Try to load the driver */
    Status = ZwSetSystemInformation(SystemLoadGdiDriverInformation,
                                    pDriverInfo,
                                    sizeof(SYSTEM_GDI_DRIVER_INFORMATION));
    if (!NT_SUCCESS(Status))
    {
        ERR("Failed to load a GDI driver: '%wZ', Status = 0x%lx\n",
            pustrPathName, Status);

        /* Free the allocated memory */
        ExFreePoolWithTag(pDriverInfo, GDITAG_LDEV);
        return FALSE;
    }

    /* Set the driver info */
    pldev->pGdiDriverInfo = pDriverInfo;

    /* Return success. */
    return TRUE;
}
Exemple #20
0
/*
 * @implemented
 */
NTSTATUS
CreateNewVolumeName(OUT PUNICODE_STRING VolumeName,
                    IN PGUID VolumeGuid OPTIONAL)
{
    GUID Guid;
    NTSTATUS Status;
    UNICODE_STRING GuidString;

    /* If no GUID was provided, then create one */
    if (!VolumeGuid)
    {
        Status = ExUuidCreate(&Guid);
        if (!NT_SUCCESS(Status))
        {
            return Status;
        }
    }
    else
    {
        RtlCopyMemory(&Guid, VolumeGuid, sizeof(GUID));
    }

    /* Convert GUID to string */
    Status = RtlStringFromGUID(&Guid, &GuidString);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    /* Size for volume namespace, litteral GUID, and null char */
    VolumeName->MaximumLength = 0x14 + 0x4C + sizeof(UNICODE_NULL);
    VolumeName->Buffer = AllocatePool(0x14 + 0x4C + sizeof(UNICODE_NULL));
    if (!VolumeName->Buffer)
    {
        Status = STATUS_INSUFFICIENT_RESOURCES;
    }
    else
    {
        RtlCopyUnicodeString(VolumeName, &Volume);
        RtlAppendUnicodeStringToString(VolumeName, &GuidString);
        VolumeName->Buffer[VolumeName->Length / sizeof(WCHAR)] = UNICODE_NULL;
        Status = STATUS_SUCCESS;
    }

    ExFreePoolWithTag(GuidString.Buffer, 0);

    return Status;
}
/*++

Routine Description:

	创建一个新的上下文
    This routine creates a new file context

Arguments:

    FileName            - Supplies the file name
    FileContext         - Returns the file context

Return Value:

    Status

--*/
NTSTATUS
CtxCreateFileContext (
    __in PUNICODE_STRING FileName,
    __deref_out PCTX_FILE_CONTEXT *FileContext
    )
{
    NTSTATUS status;
    PCTX_FILE_CONTEXT fileContext;

    PAGED_CODE();

    //  分配一个文件上下文
    //  Allocate a file context
    //

    DebugTrace(DEBUG_TRACE_FILE_CONTEXT_OPERATIONS, ("[Ctx]: Allocating file context \n"));

    status = FltAllocateContext( Globals.Filter,
                                 FLT_FILE_CONTEXT,
                                 CTX_FILE_CONTEXT_SIZE,
                                 PagedPool,
                                 &fileContext );

    if (!NT_SUCCESS( status )) 
	{
        DebugTrace( DEBUG_TRACE_FILE_CONTEXT_OPERATIONS | DEBUG_TRACE_ERROR,
                    ("[Ctx]: Failed to allocate file context with status 0x%x \n",
                     status) );
        return status;
    }

    //  初始化新创建的上下文
    //  Initialize the newly created context

    //  分配内存,并拷贝文件名
    //  Allocate and copy off the file name
    fileContext->FileName.MaximumLength = FileName->Length;
    status = CtxAllocateUnicodeString( &fileContext->FileName );
    if (NT_SUCCESS( status )) {

        RtlCopyUnicodeString( &fileContext->FileName, FileName );
    }

    *FileContext = fileContext;

    return STATUS_SUCCESS;
}
Exemple #22
0
NTSTATUS
SoundCreateDeviceName(
    PCWSTR PrePrefix,
    PCWSTR Prefix,
    UCHAR  Index,
    PUNICODE_STRING DeviceName
)
{
    UNICODE_STRING Number;
    WCHAR NumberBuffer[5];
    UNICODE_STRING uPrePrefix;
    UNICODE_STRING uPrefix;
    ULONG Size;

    RtlInitUnicodeString(&uPrePrefix, PrePrefix);
    RtlInitUnicodeString(&uPrefix, Prefix);
    Size = uPrePrefix.Length + uPrefix.Length + sizeof(NumberBuffer) +
           sizeof(UNICODE_NULL);

    DeviceName->Buffer = ExAllocatePool(PagedPool, Size);
    DeviceName->MaximumLength = (USHORT)Size;

    if (DeviceName->Buffer == NULL) {
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    RtlCopyUnicodeString(DeviceName, &uPrePrefix);
    RtlAppendUnicodeStringToString(DeviceName, &uPrefix);

    if (Index != 255) {
        Number.Buffer = NumberBuffer;
        Number.MaximumLength = sizeof(NumberBuffer);

        RtlIntegerToUnicodeString((ULONG)Index, 10, &Number);

        RtlAppendUnicodeStringToString(DeviceName, &Number);
    }

    /*
    **  Null terminate for some uses (but don't increase the 'length' or
    **  the UNICODE_STRING version will have a 0 on the end.
    */

    DeviceName->Buffer[DeviceName->Length / sizeof(UNICODE_NULL)] = UNICODE_NULL;

    return STATUS_SUCCESS;
}
Exemple #23
0
static PALIAS_HEADER
IntCreateAliasHeader(PCONSRV_CONSOLE Console,
                     PVOID    ExeName,
                     USHORT   ExeLength,
                     BOOLEAN  UnicodeExe)
{
    UNICODE_STRING ExeNameU;

    PALIAS_HEADER Entry;

    if (ExeName == NULL) return NULL;

    if (UnicodeExe)
    {
        ExeNameU.Buffer = ExeName;
        /* Length is in bytes */
        ExeNameU.MaximumLength = ExeLength;
    }
    else
    {
        if (!ConvertInputAnsiToUnicode(Console,
                                       ExeName, ExeLength,
                                       &ExeNameU.Buffer, &ExeNameU.MaximumLength))
        {
            return NULL;
        }
    }
    ExeNameU.Length = ExeNameU.MaximumLength;

    Entry = ConsoleAllocHeap(0, sizeof(ALIAS_HEADER) + ExeNameU.Length);
    if (!Entry)
    {
        if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
        return Entry;
    }

    Entry->ExeName.Buffer = (PWSTR)(Entry + 1);
    Entry->ExeName.Length = 0;
    Entry->ExeName.MaximumLength = ExeNameU.Length;
    RtlCopyUnicodeString(&Entry->ExeName, &ExeNameU);

    Entry->Data = NULL;
    Entry->Next = NULL;

    if (!UnicodeExe) ConsoleFreeHeap(ExeNameU.Buffer);
    return Entry;
}
Exemple #24
0
//--------------------------------------------------------------------------------------
NTSTATUS DriverEntry(PDRIVER_OBJECT DriverObject, PUNICODE_STRING RegistryPath)
{    
    DbgMsg(__FILE__, __LINE__, __FUNCTION__"()\n");  

    DriverObject->DriverUnload = DriverUnload;
    m_Self = (PLDR_DATA_TABLE_ENTRY)DriverObject->DriverSection;

    KeInitializeMutex(&m_GlobalMutex, NULL); 

    // save registry path
    if (AllocUnicodeString(&m_RegistryPath, RegistryPath->Length))
    {
        RtlCopyUnicodeString(&m_RegistryPath, RegistryPath);
        DbgMsg(__FILE__, __LINE__, "Service registry path is '%wZ'\n", &m_RegistryPath);
    }
    else
    {
        return STATUS_UNSUCCESSFUL;
    }

    NTSTATUS ns = PsSetLoadImageNotifyRoutine(LoadImageNotify);
    if (!NT_SUCCESS(ns))
    {
        DbgMsg(__FILE__, __LINE__, "PsSetLoadImageNotifyRoutine() fails; status: 0x%.8x\n", ns);
        return STATUS_UNSUCCESSFUL;
    }

    PIMAGE_NT_HEADERS32 pHeaders = (PIMAGE_NT_HEADERS32)((PUCHAR)m_Self->DllBase + 
        ((PIMAGE_DOS_HEADER)m_Self->DllBase)->e_lfanew);

    PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)
        (pHeaders->FileHeader.SizeOfOptionalHeader + 
        (PUCHAR)&pHeaders->OptionalHeader);
    
    // copy sections
    for (ULONG i = 0; i < pHeaders->FileHeader.NumberOfSections; i++)
    {            
        // erase discardable flag from our driver sections
        pSection->Characteristics &= ~IMAGE_SCN_MEM_DISCARDABLE;             
        pSection += 1;
    } 

    m_RequiredSize = pHeaders->OptionalHeader.SizeOfImage;

    return STATUS_SUCCESS;
}
Exemple #25
0
VOID
WINAPI
InitCommandLines(VOID)
{
    PRTL_USER_PROCESS_PARAMETERS Params;

    /* get command line */
    Params = NtCurrentPeb()->ProcessParameters;
    RtlNormalizeProcessParams (Params);

    /* initialize command line buffers */
    CommandLineStringW.Length = Params->CommandLine.Length;
    CommandLineStringW.MaximumLength = CommandLineStringW.Length + sizeof(WCHAR);
    CommandLineStringW.Buffer = RtlAllocateHeap(GetProcessHeap(),
                                                HEAP_GENERATE_EXCEPTIONS | HEAP_ZERO_MEMORY,
                                                CommandLineStringW.MaximumLength);
    if (CommandLineStringW.Buffer == NULL)
    {
        return;
    }

    RtlInitAnsiString(&CommandLineStringA, NULL);

    /* Copy command line */
    RtlCopyUnicodeString(&CommandLineStringW,
                         &(Params->CommandLine));
    CommandLineStringW.Buffer[CommandLineStringW.Length / sizeof(WCHAR)] = 0;

    /* convert unicode string to ansi (or oem) */
    if (bIsFileApiAnsi)
        RtlUnicodeStringToAnsiString(&CommandLineStringA,
                                     &CommandLineStringW,
                                     TRUE);
    else
        RtlUnicodeStringToOemString(&CommandLineStringA,
                                    &CommandLineStringW,
                                    TRUE);

    CommandLineStringA.Buffer[CommandLineStringA.Length] = 0;

    bCommandLineInitialized = TRUE;
}
Exemple #26
0
//read EnableReplace key from reg to check if replace the key with our define key
void ReadRegistery(IN PUNICODE_STRING RegistryPath)
{
	UNICODE_STRING              parameter_path;
	RTL_QUERY_REGISTRY_TABLE    query_table[2];
	NTSTATUS                    status;

	parameter_path.Length = 0;
	parameter_path.MaximumLength = RegistryPath->Length + sizeof(PARAMETER_KEY);
	parameter_path.Buffer = (PWSTR) ExAllocatePool(PagedPool, parameter_path.MaximumLength);

	if (parameter_path.Buffer == NULL)
	{
		return;
	}
    RtlZeroMemory(parameter_path.Buffer,parameter_path.MaximumLength);

	RtlCopyUnicodeString(&parameter_path, RegistryPath);

	RtlAppendUnicodeToString(&parameter_path, PARAMETER_KEY);

	RtlZeroMemory(&query_table[0], sizeof(query_table));

	query_table[0].Flags = RTL_QUERY_REGISTRY_DIRECT | RTL_QUERY_REGISTRY_REQUIRED;
	query_table[0].Name = ENABLEWRITEPORT_VALUE;
	query_table[0].EntryContext = &bEnableReplace;

	status = RtlQueryRegistryValues(
		RTL_REGISTRY_ABSOLUTE,
		parameter_path.Buffer,
		&query_table[0],
		NULL,
		NULL
		);

	ExFreePool(parameter_path.Buffer);

	if (!NT_SUCCESS(status))
	{
		KdPrint(("Kb_sniff_Mp: Query registry failed.\n"));
	}
}
Exemple #27
0
void 
NTAPI
WallALERecvAcceptClassify(
   IN const FWPS_INCOMING_VALUES* inFixedValues,
   IN const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
   IN OUT void* layerData,
   IN const void* classifyContext,
   IN const FWPS_FILTER* filter,
   IN UINT64 flowContext,
   OUT FWPS_CLASSIFY_OUT* classifyOut
   )
/*++
--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    UNICODE_STRING          devName,dosName;
    WCHAR                   buffer[MAX_PATH_LEN];
    PMY_UNICODE_STRING      logData;
    PWALL_PENDED_PACKET     pendedRecv = NULL;
    BOOLEAN                 bWakeUp = FALSE;
    ADDRESS_FAMILY          addressFamily;

    LOG("into\n");


    if(!(classifyOut->rights & FWPS_RIGHT_ACTION_WRITE))
    {
        KdPrint(("write right not set!\n"));
        return;
    }

    if( layerData != NULL )
    {
        FWPS_PACKET_INJECTION_STATE state;
        state = FwpsQueryPacketInjectionState( gInjectHandle,
                                       layerData,
                                       NULL);
        KdPrint(("inject state:%x\n",state ));
        if( state == FWPS_PACKET_INJECTED_BY_SELF ||
            state == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF )
        {
            classifyOut->actionType = FWP_ACTION_PERMIT;
            KdPrint(("inject by self\n"));
            goto exit;
        }
    }
    addressFamily = GetAddressFamilyForLayer(inFixedValues->layerId);

    if(!IsAleReauthorize(inFixedValues))
    {
        pendedRecv = WallAllocateAndInitPendedPacket( inFixedValues,
                                                    inMetaValues,
                                                    addressFamily,
                                                    layerData,
                                                    WALL_DATA_PACKET,
                                                    FWP_DIRECTION_INBOUND );
        if(pendedRecv == NULL )
        {
            classifyOut->actionType = FWP_ACTION_BLOCK;
            classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
            goto exit;
        }

        ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, 
                                            FWPS_METADATA_FIELD_COMPLETION_HANDLE));

        status = FwpsPendOperation0(
                  inMetaValues->completionHandle,
                  &pendedRecv->completionContext
                  );

        if (!NT_SUCCESS(status))
        {
            classifyOut->actionType = FWP_ACTION_BLOCK;
            classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
            classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
            goto exit;
        }

        bWakeUp = IsListEmpty(&gPacketList->list) &&
                                       IsListEmpty(&gConnList->list);

        ExInterlockedInsertTailList( &gPacketList->list,&pendedRecv->list,&gPacketList->lock );
        pendedRecv = NULL;

        if( bWakeUp )
        {
            RunMyProcess( WallInspectWallPackets,NULL );
        }

        classifyOut->actionType = FWP_ACTION_BLOCK;
        classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
        classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
    }
    else
    {//reauth

        FWP_DIRECTION packetDirection;
        KIRQL         irql,irql2;


        KdPrint(("recv reauth!\n"));
        classifyOut->actionType = FWP_ACTION_BLOCK;
        classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
        classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
    }


exit:
    if( classifyOut->actionType == FWP_ACTION_PERMIT )
    {
        RtlInitUnicodeString( &devName,(PWCHAR)inMetaValues->processPath->data );
        RtlInitEmptyUnicodeString( &dosName,buffer,MAX_PATH_LEN * sizeof(WCHAR));
        logData = MyExAllocatePool( sizeof( MY_UNICODE_STRING) + inMetaValues->processPath->size);
        if( logData != NULL)
        {
            logData->str.Buffer = logData->buffer;
            logData->str.MaximumLength = (USHORT)inMetaValues->processPath->size;
            status = DevicePathToDosPath( &devName,&dosName );
            if( NT_SUCCESS( status ))
            {
                RtlCopyUnicodeString( (PUNICODE_STRING)logData,&dosName );
            }
            else
            {
                RtlCopyUnicodeString( (PUNICODE_STRING)logData,&devName );
            }
            RunMyProcess( WallWriteConnectLogData,logData );
            logData = NULL;
        }
        
    }
    return;
}
Exemple #28
0
void 
NTAPI
WallALEConnectClassify(
   IN const FWPS_INCOMING_VALUES* inFixedValues,
   IN const FWPS_INCOMING_METADATA_VALUES* inMetaValues,
   IN OUT void* layerData,
   IN const void* classifyContext,
   IN const FWPS_FILTER* filter,
   IN UINT64 flowContext,
   OUT FWPS_CLASSIFY_OUT* classifyOut
   )
/*++

注意:此回调的Irql <= DISPATCH_LEVEL!!!!!
--*/
{
    NTSTATUS                status = STATUS_SUCCESS;
    PWALL_PENDED_PACKET     pendedConn = NULL;
    BOOLEAN                 bWakeUp = FALSE;
    ADDRESS_FAMILY          addressFamily;
    UNICODE_STRING          devName,dosName;
    WCHAR                   buffer[MAX_PATH_LEN];
    PMY_UNICODE_STRING      logData = NULL;

    LOG("into\n");

    if(!(classifyOut->rights & FWPS_RIGHT_ACTION_WRITE))
    {
        KdPrint(("write right not set!\n"));
        return;
    }

     if( layerData != NULL )
     {
         FWPS_PACKET_INJECTION_STATE state;
         state = FwpsQueryPacketInjectionState( gInjectHandle,
                                        layerData,
                                        NULL);
         if( state == FWPS_PACKET_INJECTED_BY_SELF ||
             state == FWPS_PACKET_PREVIOUSLY_INJECTED_BY_SELF )
         {
             classifyOut->actionType = FWP_ACTION_PERMIT;
             goto exit;
         }
     }

    addressFamily = GetAddressFamilyForLayer(inFixedValues->layerId);

    if(!IsAleReauthorize(inFixedValues))
    {
        pendedConn = WallAllocateAndInitPendedPacket( inFixedValues,
                                                    inMetaValues,
                                                    addressFamily,
                                                    layerData,
                                                    WALL_CONNECT_PACKET,
                                                    FWP_DIRECTION_OUTBOUND );
        if(pendedConn == NULL )
        {
            classifyOut->actionType = FWP_ACTION_BLOCK;
            classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
            goto exit;
        }

        ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, 
                                            FWPS_METADATA_FIELD_COMPLETION_HANDLE));

        status = FwpsPendOperation0(
                  inMetaValues->completionHandle,
                  &pendedConn->completionContext
                  );

        if (!NT_SUCCESS(status))
        {
            classifyOut->actionType = FWP_ACTION_BLOCK;
            classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
            goto exit;
        }

        bWakeUp = IsListEmpty(&gPacketList->list) &&
                                       IsListEmpty(&gConnList->list);

        ExInterlockedInsertTailList( &gConnList->list,&pendedConn->list,&gConnList->lock );
        pendedConn = NULL;

        if( bWakeUp )
        {
            RunMyProcess( WallInspectWallPackets,NULL );
        }

        classifyOut->actionType = FWP_ACTION_BLOCK;
        classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
    }
    else
    {//reauth

        FWP_DIRECTION packetDirection;
        KIRQL         irql,irql2;

        LOG("1\n");

        ASSERT(FWPS_IS_METADATA_FIELD_PRESENT(inMetaValues, 
                                            FWPS_METADATA_FIELD_PACKET_DIRECTION));
        packetDirection = inMetaValues->packetDirection;

        if (packetDirection == FWP_DIRECTION_OUTBOUND)
        {
            LIST_ENTRY* listEntry;
            BOOLEAN authComplete = FALSE;
            
             LOG("2\n");
            KeAcquireSpinLock( &gConnList->lock,&irql );
            LOG("22\n");
            for (listEntry = gConnList->list.Flink;
              listEntry != (PLIST_ENTRY)gConnList;
              )
            {   
                pendedConn = (PWALL_PENDED_PACKET)listEntry;
                listEntry = listEntry->Flink;

                if (IsMatchingConnectPacket(
                     inFixedValues,
                     addressFamily,
                     packetDirection,
                     pendedConn
                  ) && (pendedConn->authConnectDecision != 0))
                {

                    ASSERT((pendedConn->authConnectDecision == FWP_ACTION_PERMIT) ||
                      (pendedConn->authConnectDecision == FWP_ACTION_BLOCK));
                LOG("3\n");
                    classifyOut->actionType = pendedConn->authConnectDecision;
                    if( classifyOut->actionType == FWP_ACTION_BLOCK ){
                        classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
                        classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
                    }

                    RemoveEntryList(&pendedConn->list);
               
                    if (/*!gDriverUnloading &&*/
                       (pendedConn->netBufferList != NULL) &&
                       (pendedConn->authConnectDecision == FWP_ACTION_PERMIT))
                    {
                  
                        pendedConn->type = WALL_DATA_PACKET;
                         LOG("4\n");
                        KeAcquireSpinLock( &gPacketList->lock,&irql2 );

                        bWakeUp = IsListEmpty(&gPacketList->list) &&
                                       IsListEmpty(&gConnList->list);

                        InsertTailList(&gPacketList->list, &pendedConn->list);
                        pendedConn = NULL; // ownership transferred

                        KeReleaseSpinLock( &gPacketList->lock,irql2 );

                        if (bWakeUp)
                        {
                            RunMyProcess( WallInspectWallPackets,NULL );
                        }
                    }//end if permit

                    authComplete = TRUE;
                    break;
                }//end if match
            }//end if for

            KeReleaseSpinLock( &gConnList->lock,irql );
            if (authComplete)
            {
                 LOG("5\n");
                goto exit;
            }
            else
            {
                pendedConn = NULL;
            }
        }//end if outbound

        classifyOut->actionType = FWP_ACTION_BLOCK;
        classifyOut->rights &= ~FWPS_RIGHT_ACTION_WRITE;
        classifyOut->flags |= FWPS_CLASSIFY_OUT_FLAG_ABSORB;
    }
exit:
    if( pendedConn != NULL )
    {
        LOG("free packet\n");
        WallFreePendedPacket( pendedConn );
        pendedConn = NULL;
    }

    if( classifyOut->actionType == FWP_ACTION_PERMIT )
    {
        RtlInitUnicodeString( &devName,(PWCHAR)inMetaValues->processPath->data );
        RtlInitEmptyUnicodeString( &dosName,buffer,MAX_PATH_LEN * sizeof(WCHAR));
        logData = MyExAllocatePool( sizeof( MY_UNICODE_STRING) + inMetaValues->processPath->size);
        if( logData != NULL)
        {
            logData->str.Buffer = logData->buffer;
            logData->str.MaximumLength = (USHORT)inMetaValues->processPath->size;
            status = DevicePathToDosPath( &devName,&dosName );
            if( NT_SUCCESS( status ))
            {
                RtlCopyUnicodeString( (PUNICODE_STRING)logData,&dosName );
            }
            else
            {
                RtlCopyUnicodeString( (PUNICODE_STRING)logData,&devName );
            }
            KdPrint(("logData:%wZ\n",logData ));

            RunMyProcess( WallWriteConnectLogData,logData );
            logData = NULL;
        }
        
    }
    return;
}
Exemple #29
0
/* Calls ClientLoadLibrary in user32 */
BOOL
NTAPI
co_IntClientLoadLibrary(PUNICODE_STRING pstrLibName,
                        PUNICODE_STRING pstrInitFunc,
                        BOOL Unload,
                        BOOL ApiHook)
{
   PVOID ResultPointer;
   ULONG ResultLength;
   ULONG ArgumentLength;
   PCLIENT_LOAD_LIBRARY_ARGUMENTS pArguments;
   NTSTATUS Status;
   BOOL bResult;
   ULONG_PTR pLibNameBuffer = 0, pInitFuncBuffer = 0;

   /* Do not allow the desktop thread to do callback to user mode */
   ASSERT(PsGetCurrentThreadWin32Thread() != gptiDesktopThread);

   TRACE("co_IntClientLoadLibrary: %S, %S, %d, %d\n", pstrLibName->Buffer, pstrLibName->Buffer, Unload, ApiHook);

   /* Calculate the size of the argument */
   ArgumentLength = sizeof(CLIENT_LOAD_LIBRARY_ARGUMENTS);
   if(pstrLibName)
   {
       pLibNameBuffer = ArgumentLength;
       ArgumentLength += pstrLibName->Length + sizeof(WCHAR);
   }
   if(pstrInitFunc)
   {
       pInitFuncBuffer = ArgumentLength;
       ArgumentLength += pstrInitFunc->Length + sizeof(WCHAR);
   }

   /* Allocate the argument */
   pArguments = IntCbAllocateMemory(ArgumentLength);
   if(pArguments == NULL)
   {
       return FALSE;
   }

   /* Fill the argument */
   pArguments->Unload = Unload;
   pArguments->ApiHook = ApiHook;
   if(pstrLibName)
   {
       /* Copy the string to the callback memory */
       pLibNameBuffer += (ULONG_PTR)pArguments;
       pArguments->strLibraryName.Buffer = (PWCHAR)pLibNameBuffer;
       pArguments->strLibraryName.MaximumLength = pstrLibName->Length + sizeof(WCHAR);
       RtlCopyUnicodeString(&pArguments->strLibraryName, pstrLibName);

       /* Fix argument pointer to be relative to the argument */
       pLibNameBuffer -= (ULONG_PTR)pArguments;
       pArguments->strLibraryName.Buffer = (PWCHAR)(pLibNameBuffer);
   }
   else
   {
       RtlZeroMemory(&pArguments->strLibraryName, sizeof(UNICODE_STRING));
   }

   if(pstrInitFunc)
   {
       /* Copy the strings to the callback memory */
       pInitFuncBuffer += (ULONG_PTR)pArguments;
       pArguments->strInitFuncName.Buffer = (PWCHAR)pInitFuncBuffer;
       pArguments->strInitFuncName.MaximumLength = pstrInitFunc->Length + sizeof(WCHAR);
       RtlCopyUnicodeString(&pArguments->strInitFuncName, pstrInitFunc);

       /* Fix argument pointers to be relative to the argument */
       pInitFuncBuffer -= (ULONG_PTR)pArguments;
       pArguments->strInitFuncName.Buffer = (PWCHAR)(pInitFuncBuffer);
   }
   else
   {
       RtlZeroMemory(&pArguments->strInitFuncName, sizeof(UNICODE_STRING));
   }

   /* Do the callback */
   UserLeaveCo();

   Status = KeUserModeCallback(USER32_CALLBACK_CLIENTLOADLIBRARY,
                               pArguments,
                               ArgumentLength,
                               &ResultPointer,
                               &ResultLength);

   UserEnterCo();

   /* Free the argument */
   IntCbFreeMemory(pArguments);

   if(!NT_SUCCESS(Status))
   {
       return FALSE;
   }

   _SEH2_TRY
   {
       /* Probe and copy the usermode result data */
       ProbeForRead(ResultPointer, sizeof(HMODULE), 1);
       bResult = *(BOOL*)ResultPointer;
   }
   _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
   {
       bResult = FALSE;
   }
   _SEH2_END;

   return bResult;
}
Exemple #30
0
static
VOID
NTAPI
TestSymlinks(VOID)
{
    HANDLE ReparseHandle;
    NTSTATUS Status;
    IO_STATUS_BLOCK IoStatusBlock;
    OBJECT_ATTRIBUTES ObjectAttributes;
    PREPARSE_DATA_BUFFER Reparse;
    FILE_DISPOSITION_INFORMATION ToDelete;
    PFILE_OBJECT FileObject;
    UNICODE_STRING SysDir, Foobar, Regedit;
    ULONG Size;

    /* Get Windows/ReactOS directory */
    InitializeObjectAttributes(&ObjectAttributes,
                               &SystemRoot,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);
    Status = ZwOpenFile(&ReparseHandle,
                        FILE_READ_DATA,
                        &ObjectAttributes,
                        &IoStatusBlock,
                        FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                        FILE_DIRECTORY_FILE);
    if (skip(NT_SUCCESS(Status), "Opening \\SystemRoot failed: %lx\n", Status))
    {
        return;
    }

    Status = ObReferenceObjectByHandle(ReparseHandle,
                                       FILE_READ_DATA,
                                       *IoFileObjectType,
                                       UserMode,
                                       (PVOID *)&FileObject,
                                       NULL);
    if (skip(NT_SUCCESS(Status), "Querying name failed: %lx\n", Status))
    {
        ZwClose(ReparseHandle);
        return;
    }

    SysDir.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\??\\C:"));
    if (skip(SysDir.Buffer != NULL, "Allocating memory failed\n"))
    {
        ObDereferenceObject(FileObject);
        ZwClose(ReparseHandle);
        return;
    }

    SysDir.Length = sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL);
    SysDir.MaximumLength = FileObject->FileName.Length + sizeof(L"\\??\\C:");
    RtlCopyMemory(SysDir.Buffer, L"\\??\\C:", sizeof(L"\\??\\C:") - sizeof(UNICODE_NULL));
    RtlAppendUnicodeStringToString(&SysDir, &FileObject->FileName);

    Foobar.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\foobar.exe"));
    if (skip(Foobar.Buffer != NULL, "Allocating memory failed\n"))
    {
        ExFreePool(SysDir.Buffer);
        ObDereferenceObject(FileObject);
        ZwClose(ReparseHandle);
        return;
    }

    Foobar.Length = 0;
    Foobar.MaximumLength = FileObject->FileName.Length + sizeof(L"\\foobar.exe");
    RtlCopyUnicodeString(&Foobar, &FileObject->FileName);
    RtlCopyMemory(&Foobar.Buffer[Foobar.Length / sizeof(WCHAR)], L"\\foobar.exe", sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL));
    Foobar.Length += (sizeof(L"\\foobar.exe") - sizeof(UNICODE_NULL));

    Regedit.Buffer = ExAllocatePool(NonPagedPool, FileObject->FileName.Length + sizeof(L"\\regedit.exe"));
    if (skip(Regedit.Buffer != NULL, "Allocating memory failed\n"))
    {
        ExFreePool(Foobar.Buffer);
        ExFreePool(SysDir.Buffer);
        ObDereferenceObject(FileObject);
        ZwClose(ReparseHandle);
        return;
    }

    Regedit.Length = 0;
    Regedit.MaximumLength = FileObject->FileName.Length + sizeof(L"\\regedit.exe");
    RtlCopyUnicodeString(&Regedit, &FileObject->FileName);
    RtlCopyMemory(&Regedit.Buffer[Regedit.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL));
    Regedit.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL));

    ObDereferenceObject(FileObject);
    ZwClose(ReparseHandle);

    ToDelete.DeleteFile = TRUE;
    Size = FIELD_OFFSET(REPARSE_DATA_BUFFER, SymbolicLinkReparseBuffer.PathBuffer) + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL);

    InitializeObjectAttributes(&ObjectAttributes,
                               &SystemRootFoobar,
                               OBJ_CASE_INSENSITIVE,
                               NULL,
                               NULL);
    Status = ZwCreateFile(&ReparseHandle,
                          GENERIC_READ | GENERIC_WRITE | DELETE,
                          &ObjectAttributes,
                          &IoStatusBlock,
                          NULL,
                          FILE_ATTRIBUTE_NORMAL,
                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                          FILE_SUPERSEDE,
                          FILE_NON_DIRECTORY_FILE,
                          NULL,
                          0);
    ok_eq_hex(Status, STATUS_SUCCESS);
    if (skip(NT_SUCCESS(Status), "Creating file failed: %lx\n", Status))
    {
        ExFreePool(Regedit.Buffer);
        ExFreePool(Foobar.Buffer);
        ExFreePool(SysDir.Buffer);
        return;
    }

    Reparse = ExAllocatePool(NonPagedPool, Size);
    RtlZeroMemory(Reparse, Size);
    Reparse->ReparseTag = IO_REPARSE_TAG_SYMLINK;
    Reparse->ReparseDataLength = 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL);
    Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL);
    Reparse->SymbolicLinkReparseBuffer.PrintNameLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(L"\\??\\");
    Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset = Reparse->SymbolicLinkReparseBuffer.PrintNameLength;
    RtlCopyMemory(Reparse->SymbolicLinkReparseBuffer.PathBuffer,
                  (WCHAR *)((ULONG_PTR)SysDir.Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL)),
                  SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL));
    RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + SysDir.Length - sizeof(L"\\??\\") + sizeof(UNICODE_NULL)),
                  L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL));
    RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset),
                  SysDir.Buffer, SysDir.Length);
    RtlCopyMemory((WCHAR *)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset + SysDir.Length),
                  L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL));

    Status = ZwFsControlFile(ReparseHandle,
                             NULL,
                             NULL,
                             NULL,
                             &IoStatusBlock,
                             FSCTL_SET_REPARSE_POINT,
                             Reparse,
                             Size,
                             NULL,
                             0);
    ok_eq_hex(Status, STATUS_SUCCESS);
    if (!NT_SUCCESS(Status))
    {
        ZwClose(ReparseHandle);

        Status = ZwCreateFile(&ReparseHandle,
                              FILE_WRITE_ATTRIBUTES | DELETE | SYNCHRONIZE,
                              &ObjectAttributes,
                              &IoStatusBlock,
                              NULL,
                              FILE_ATTRIBUTE_NORMAL,
                              0,
                              FILE_SUPERSEDE,
                              FILE_NON_DIRECTORY_FILE  | FILE_OPEN_REPARSE_POINT | FILE_SYNCHRONOUS_IO_NONALERT | FILE_OPEN_FOR_BACKUP_INTENT,
                              NULL,
                              0);
        if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status))
        {
            Status = ZwOpenFile(&ReparseHandle,
                                DELETE,
                                &ObjectAttributes,
                                &IoStatusBlock,
                                FILE_SHARE_DELETE,
                                FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE);
            ok_eq_hex(Status, STATUS_SUCCESS);
            ZwClose(ReparseHandle);
            ExFreePool(Regedit.Buffer);
            ExFreePool(Foobar.Buffer);
            ExFreePool(SysDir.Buffer);
            ExFreePool(Reparse);
            return;
        }

        Status = ZwFsControlFile(ReparseHandle,
                                 NULL,
                                 NULL,
                                 NULL,
                                 &IoStatusBlock,
                                 FSCTL_SET_REPARSE_POINT,
                                 Reparse,
                                 Size,
                                 NULL,
                                 0);
    }

    if (skip(NT_SUCCESS(Status), "Creating symlink failed: %lx\n", Status))
    {
        ZwSetInformationFile(ReparseHandle,
                             &IoStatusBlock,
                             &ToDelete,
                             sizeof(ToDelete),
                             FileDispositionInformation);
        ZwClose(ReparseHandle);
        ExFreePool(Regedit.Buffer);
        ExFreePool(Foobar.Buffer);
        ExFreePool(SysDir.Buffer);
        ExFreePool(Reparse);
        return;
    }

    ZwClose(ReparseHandle);

    Status = ZwCreateFile(&ReparseHandle,
                          GENERIC_READ,
                          &ObjectAttributes,
                          &IoStatusBlock,
                          NULL,
                          FILE_ATTRIBUTE_NORMAL,
                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                          FILE_OPEN,
                          FILE_NON_DIRECTORY_FILE,
                          NULL,
                          0);
    ok(Status == STATUS_SUCCESS || /* Windows Vista+ */
       Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */
        "ZwCreateFile returned unexpected status: %lx\n", Status);
    if (NT_SUCCESS(Status))
    {
        Status = ObReferenceObjectByHandle(ReparseHandle,
                                           FILE_READ_DATA,
                                           *IoFileObjectType,
                                           UserMode,
                                           (PVOID *)&FileObject,
                                           NULL);
        ok_eq_hex(Status, STATUS_SUCCESS);
        if (NT_SUCCESS(Status))
        {
            ok(RtlCompareUnicodeString(&Regedit, &FileObject->FileName, TRUE) == 0,
               "Expected: %wZ. Opened: %wZ\n", &Regedit, &FileObject->FileName);
            ObDereferenceObject(FileObject);
        }

        ZwClose(ReparseHandle);
    }

    ExFreePool(Regedit.Buffer);

    Status = IoCreateFile(&ReparseHandle,
                          GENERIC_READ,
                          &ObjectAttributes,
                          &IoStatusBlock,
                          NULL,
                          FILE_ATTRIBUTE_NORMAL,
                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                          FILE_OPEN,
                          FILE_NON_DIRECTORY_FILE,
                          NULL,
                          0,
                          CreateFileTypeNone,
                          NULL,
                          IO_NO_PARAMETER_CHECKING | IO_STOP_ON_SYMLINK);
    ok(Status == STATUS_STOPPED_ON_SYMLINK || /* Windows Vista+ */
       Status == STATUS_IO_REPARSE_TAG_NOT_HANDLED, /* Windows 2003 (SP1, SP2) */
        "ZwCreateFile returned unexpected status: %lx\n", Status);
    if (NT_SUCCESS(Status))
    {
        ZwClose(ReparseHandle);
    }

    Status = ZwCreateFile(&ReparseHandle,
                          GENERIC_READ | GENERIC_WRITE | DELETE,
                          &ObjectAttributes,
                          &IoStatusBlock,
                          NULL,
                          FILE_ATTRIBUTE_NORMAL,
                          FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
                          FILE_OPEN,
                          FILE_NON_DIRECTORY_FILE | FILE_OPEN_REPARSE_POINT | FILE_OPEN_FOR_BACKUP_INTENT,
                          NULL,
                          0);
    if (skip(NT_SUCCESS(Status), "Creating opening reparse point: %lx\n", Status))
    {
        Status = ZwOpenFile(&ReparseHandle,
                            DELETE,
                            &ObjectAttributes,
                            &IoStatusBlock,
                            FILE_SHARE_DELETE,
                            FILE_NON_DIRECTORY_FILE | FILE_DELETE_ON_CLOSE);
        ok_eq_hex(Status, STATUS_SUCCESS);
        ZwClose(ReparseHandle);
        ExFreePool(Foobar.Buffer);
        ExFreePool(SysDir.Buffer);
        ExFreePool(Reparse);
        return;
    }

    Status = ObReferenceObjectByHandle(ReparseHandle,
                                       FILE_READ_DATA,
                                       *IoFileObjectType,
                                       UserMode,
                                       (PVOID *)&FileObject,
                                       NULL);
    ok_eq_hex(Status, STATUS_SUCCESS);
    if (NT_SUCCESS(Status))
    {
        ok(RtlCompareUnicodeString(&Foobar, &FileObject->FileName, TRUE) == 0,
           "Expected: %wZ. Opened: %wZ\n", &Foobar, &FileObject->FileName);
        ObDereferenceObject(FileObject);
    }

    ExFreePool(Foobar.Buffer);

    RtlZeroMemory(Reparse, Size);
    Status = ZwFsControlFile(ReparseHandle,
                             NULL,
                             NULL,
                             NULL,
                             &IoStatusBlock,
                             FSCTL_GET_REPARSE_POINT,
                             NULL,
                             0,
                             Reparse,
                             Size);
    ok_eq_hex(Status, STATUS_SUCCESS);
    ok_eq_hex(IoStatusBlock.Information, Size);
    if (NT_SUCCESS(Status))
    {
        PWSTR Buffer;
        UNICODE_STRING ReparsePath, FullPath;

        ok_eq_hex(Reparse->ReparseTag, IO_REPARSE_TAG_SYMLINK);
        ok_eq_hex(Reparse->ReparseDataLength, 12 + SysDir.Length * 2 + sizeof(L"\\regedit.exe") * 2 - sizeof(L"\\??\\") - sizeof(UNICODE_NULL));
        ok_eq_hex(Reparse->SymbolicLinkReparseBuffer.Flags, 0);

        FullPath.Length = 0;
        FullPath.MaximumLength = SysDir.Length + sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL);
        Buffer = FullPath.Buffer = ExAllocatePool(NonPagedPool, FullPath.MaximumLength);
        if (!skip(Buffer != NULL, "Memory allocation failed!\n"))
        {
            RtlCopyUnicodeString(&FullPath, &SysDir);
            RtlCopyMemory(&FullPath.Buffer[FullPath.Length / sizeof(WCHAR)], L"\\regedit.exe", sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL));
            FullPath.Length += (sizeof(L"\\regedit.exe") - sizeof(UNICODE_NULL));
            ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.SubstituteNameOffset);
            ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.SubstituteNameLength;
            ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath);

            FullPath.Length -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL));
            FullPath.MaximumLength -= (sizeof(L"\\??\\") - sizeof(UNICODE_NULL));
            FullPath.Buffer = (PWSTR)((ULONG_PTR)Buffer + sizeof(L"\\??\\") - sizeof(UNICODE_NULL));
            ReparsePath.Buffer = (PWSTR)((ULONG_PTR)Reparse->SymbolicLinkReparseBuffer.PathBuffer + Reparse->SymbolicLinkReparseBuffer.PrintNameOffset);
            ReparsePath.Length = ReparsePath.MaximumLength = Reparse->SymbolicLinkReparseBuffer.PrintNameLength;
            ok(RtlCompareUnicodeString(&ReparsePath, &FullPath, TRUE) == 0, "Expected: %wZ. Got: %wZ\n", &ReparsePath, &FullPath);

            ExFreePool(Buffer);
        }
    }

    ExFreePool(SysDir.Buffer);
    ExFreePool(Reparse);

    ZwSetInformationFile(ReparseHandle,
                         &IoStatusBlock,
                         &ToDelete,
                         sizeof(ToDelete),
                         FileDispositionInformation);
    ZwClose(ReparseHandle);
}