Beispiel #1
0
/* Query file info from a handle, storing it in Entry */
NTSTATUS
ApphelpCacheQueryInfo(
    _In_ HANDLE ImageHandle,
    _Out_ PSHIM_CACHE_ENTRY Entry)
{
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_BASIC_INFORMATION FileBasic;
    FILE_STANDARD_INFORMATION FileStandard;
    NTSTATUS Status;

    Status = ZwQueryInformationFile(ImageHandle,
                                    &IoStatusBlock,
                                    &FileBasic,
                                    sizeof(FileBasic),
                                    FileBasicInformation);
    if (!NT_SUCCESS(Status))
    {
        return Status;
    }

    Status = ZwQueryInformationFile(ImageHandle,
                                    &IoStatusBlock,
                                    &FileStandard,
                                    sizeof(FileStandard),
                                    FileStandardInformation);
    if (NT_SUCCESS(Status))
    {
        Entry->Persistent.DateTime = FileBasic.LastWriteTime;
        Entry->Persistent.FileSize = FileStandard.EndOfFile;
    }
    return Status;
}
Beispiel #2
0
co_rc_t co_os_file_block_get_size(co_monitor_file_block_dev_t *fdev, unsigned long long *size)
{
	NTSTATUS status;
	HANDLE FileHandle;
	IO_STATUS_BLOCK IoStatusBlock;
	FILE_STANDARD_INFORMATION fsi;
	co_rc_t rc;
	bool_t opened = PFALSE;

	co_debug("%s: device %s\n", __FUNCTION__, fdev->pathname);

	if (fdev->sysdep == NULL) {
		status = co_os_open_file(fdev->pathname, &FileHandle);
		if (status != STATUS_SUCCESS)
			return CO_RC(ERROR);

		opened = TRUE;
	}
	else {
		FileHandle = (HANDLE)(fdev->sysdep);
	}

	status = ZwQueryInformationFile(FileHandle,
					&IoStatusBlock,
					&fsi,
					sizeof(fsi),
					FileStandardInformation);

	if (status == STATUS_SUCCESS) {
		*size = fsi.EndOfFile.QuadPart;
		co_debug("%s: reported size: %llu KBs\n", __FUNCTION__, (*size >> 10));
		rc = CO_RC(OK);
	}
Beispiel #3
0
NTSTATUS Log_WriteLine(PLOG_COUNTED_STRING Line)
{
	NTSTATUS Status = STATUS_SUCCESS;
	IO_STATUS_BLOCK StatusBlock;
	FILE_STANDARD_INFORMATION Info;

	if (!LogFile)
		return STATUS_INVALID_HANDLE;

	if (!InterlockedCompareExchange(&LogRotationInProgress, 1, 0))
	{
		Status = ZwQueryInformationFile(LogFile, &StatusBlock, &Info, sizeof(Info), FileStandardInformation);
		if (!NT_SUCCESS(Status)) {
			return Status;
		}

		if (Info.DeletePending && LogFileName) {
			ZwClose(LogFile);
			LogFile = NULL;
			Status = Log_StartFileLogging(LogFileName);
			if (!NT_SUCCESS(Status))
				return Status;
		}
		else if (Info.EndOfFile.QuadPart >= LogSettings.MaxFileSize) {
			Status = Log_Rotate();
		}

		LogRotationInProgress = 0;
	}

	if (NT_SUCCESS(Status) && LogFile)
		Status = ZwWriteFile(LogFile, NULL, NULL, NULL, &StatusBlock, Line->Data, Line->DataLength, NULL, NULL);

	return Status;
}
Beispiel #4
0
static
co_rc_t co_os_change_file_information(char *filename,
				      IO_STATUS_BLOCK *io_status,
				      VOID *buffer,
				      ULONG len,
				      FILE_INFORMATION_CLASS info_class,
				      co_os_change_file_info_func_t func,
				      void *data)
{
	NTSTATUS status;
	HANDLE handle;
	co_rc_t rc;

	rc = co_os_file_open(filename, &handle, FILE_READ_ATTRIBUTES | FILE_WRITE_ATTRIBUTES);
	if (!CO_OK(rc))
		return rc;

	status = ZwQueryInformationFile(handle, io_status, buffer, len, info_class);
	if (status == STATUS_SUCCESS) {
		func(data, buffer, len);
		status = ZwSetInformationFile(handle, io_status, buffer, len, info_class);
	}

	co_os_file_close(handle);

	return co_status_convert(status);
}
Beispiel #5
0
//
// Get actual file size
//
VDKSTAT	VdkGetFileSize(
	HANDLE	FileHandle,
	PINT64	FileSize)
{
	IO_STATUS_BLOCK	io_status;
	VDKSTAT			status;

	FILE_STANDARD_INFORMATION	file_standard;

	status = ZwQueryInformationFile(
		FileHandle,
		&io_status,
		&file_standard,
		sizeof(FILE_STANDARD_INFORMATION),
		FileStandardInformation);

	if (!VDKSUCCESS(status)) {
		VDKTRACE(VDKOPEN,
			("[VDK] ZwQueryInformationFile - FILE_STANDARD_INFORMATION %s\n",
			VdkStatusStr(status)));

		return status;
	}

	*FileSize = file_standard.EndOfFile.QuadPart;

	return status;
}
Beispiel #6
0
DWORD WINAPI _AvpSetFilePointer(
    HANDLE  hFile,      // handle of file
    LONG  lDistanceToMove,      // number of bytes to move file pointer
    PLONG  lpDistanceToMoveHigh,        // address of high-order word of distance to move
    DWORD  dwMoveMethod         // how to move
        )
{
        NTSTATUS ntStatus;
        IO_STATUS_BLOCK IoStatus;
        FILE_POSITION_INFORMATION FileInformation;
        DWORD newPos;
        DWORD fLen=_AvpGetFileSize(hFile,NULL);
		if (fLen==-1)return -1;

        ntStatus = ZwQueryInformationFile( hFile,
			&IoStatus,
			&FileInformation,
			sizeof( FILE_POSITION_INFORMATION ),
			FilePositionInformation );
        if (!NT_SUCCESS(ntStatus))return -1;

        switch ( dwMoveMethod ) {
                case 1:
                        newPos= FileInformation.CurrentByteOffset.LowPart + lDistanceToMove;
                        break;

                case 2:
                        newPos= fLen + lDistanceToMove;
                        break;
                case 0:
                default:
                        newPos= lDistanceToMove;
                        break;
        }
		if( (lDistanceToMove < 0) && (newPos & 0x80000000))	return -1;

        FileInformation.CurrentByteOffset.LowPart = newPos;


        ntStatus = ZwSetInformationFile( hFile,
			 &IoStatus,
			 &FileInformation,
			 sizeof( FILE_POSITION_INFORMATION ),
			 FilePositionInformation );

/*
      _DebugTrace(TraceInfo,"AvpSetFilePointer h=%d met=%d ofs=%d :pos=%d ok=%d\n",
                (int)hFile,
                dwMoveMethod,
                lDistanceToMove,
                FileInformation.CurrentByteOffset.LowPart,
                NT_SUCCESS(ntStatus)
                );
*/
    if(!NT_SUCCESS(ntStatus))
		return -1;
        return FileInformation.CurrentByteOffset.LowPart;
}
Beispiel #7
0
BOOL WINAPI _AvpReadFile (
    HANDLE  hFile,      // handle of file to read
    LPVOID  lpBuffer,   // address of buffer that receives data
    DWORD  nNumberOfBytesToRead,        // number of bytes to read
    LPDWORD  lpNumberOfBytesRead,       // address of number of bytes read
    OVERLAPPED FAR*  lpOverlapped       // address of structure for data BYTE Disk, WORD Sector ,BYTE Head ,LPBYTE Buffer)
)
{
        NTSTATUS ntStatus;
        IO_STATUS_BLOCK IoStatus;
        FILE_POSITION_INFORMATION FileInformation;
		if(lpNumberOfBytesRead)*lpNumberOfBytesRead=0;

        DWORD fLen=_AvpGetFileSize(hFile,NULL);
        if (fLen==-1)return FALSE;

        ntStatus = ZwQueryInformationFile( hFile,
                   &IoStatus,
                   &FileInformation,
                   sizeof( FILE_POSITION_INFORMATION ),
                   FilePositionInformation );

        if (!NT_SUCCESS(ntStatus))return FALSE;

        if(fLen <= FileInformation.CurrentByteOffset.LowPart )
            nNumberOfBytesToRead=0;
		else{
			DWORD nBytesToEnd = fLen-FileInformation.CurrentByteOffset.LowPart;
			if( nBytesToEnd < nNumberOfBytesToRead)
					nNumberOfBytesToRead = nBytesToEnd;
		}


        if(nNumberOfBytesToRead == 0){
                *lpNumberOfBytesRead=0;
                return TRUE;
        }

        ntStatus = ZwReadFile( hFile,
			NULL,
			NULL,
			NULL,
			&IoStatus,
			lpBuffer,
			nNumberOfBytesToRead,
			NULL,
			NULL );

        if(lpNumberOfBytesRead)*lpNumberOfBytesRead=IoStatus.Information;

//      _DebugTrace(TraceInfo,"AvpReadFile %d %d:%d Ok:%d\n",(int)hFile,nNumberOfBytesToRead,*lpNumberOfBytesRead,NT_SUCCESS(ntStatus));
        if (NT_SUCCESS(ntStatus))
                return TRUE;
        return FALSE;

}
Beispiel #8
0
NTSTATUS getFileIdHandle(HANDLE hfile, PLARGE_INTEGER result) {
  IO_STATUS_BLOCK iostatus;
  FILE_INTERNAL_INFORMATION info;
  NTSTATUS status;
  status = 
    ZwQueryInformationFile(hfile, &iostatus, &info, sizeof(info),
			   6 /* FileInternalInformation*/ );
  if (status == STATUS_SUCCESS) {
    *result = info.FileId;
  }
  return status;
}
Beispiel #9
0
static
NTSTATUS
QueryFileInfo(
    _In_ HANDLE FileHandle,
    _Out_ PVOID *Info,
    _Inout_ PSIZE_T Length,
    _In_ FILE_INFORMATION_CLASS FileInformationClass)
{
    NTSTATUS Status;
    IO_STATUS_BLOCK IoStatus;
    PVOID Buffer;

    *Info = NULL;
    if (*Length)
    {
        Buffer = KmtAllocateGuarded(*Length);
        if (skip(Buffer != NULL, "Failed to allocate %Iu bytes\n", *Length))
            return STATUS_INSUFFICIENT_RESOURCES;
    }
    else
    {
        Buffer = NULL;
    }
    RtlFillMemory(Buffer, *Length, 0xDD);
    RtlFillMemory(&IoStatus, sizeof(IoStatus), 0x55);
    _SEH2_TRY
    {
        Status = ZwQueryInformationFile(FileHandle,
                                        &IoStatus,
                                        Buffer,
                                        *Length,
                                        FileInformationClass);
    }
    _SEH2_EXCEPT(EXCEPTION_EXECUTE_HANDLER)
    {
        Status = _SEH2_GetExceptionCode();
        ok(0, "Exception %lx querying class %d with length %Iu\n",
           Status, FileInformationClass, *Length);
    }
    _SEH2_END;
    if (Status == STATUS_PENDING)
    {
        Status = ZwWaitForSingleObject(FileHandle, FALSE, NULL);
        ok_eq_hex(Status, STATUS_SUCCESS);
        Status = IoStatus.Status;
    }
    *Length = IoStatus.Information;
    *Info = Buffer;
    return Status;
}
Beispiel #10
0
NTSTATUS AddDenyFileAccessByCreateFile(__in PUNICODE_STRING puszFileFullPath)
{
	NTSTATUS			nsStatus			= STATUS_UNSUCCESSFUL;
	IO_STATUS_BLOCK		IoStatus			= {0x00};
	HANDLE				hKeFile				= NULL;
	OBJECT_ATTRIBUTES	oa					= {0x00};
	FILE_BASIC_INFORMATION	FileAttributes	= {0x00};

	do 
	{
		InitializeObjectAttributes(
			&oa, 
			puszFileFullPath, 
			OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, 
			NULL, 
			NULL
			);
		nsStatus = ZwCreateFile(
			&hKeFile,
			GENERIC_READ,
			&oa,
			&IoStatus,
			NULL,
			FILE_ATTRIBUTE_SYSTEM,
			0,
			FILE_OPEN_IF,
			FILE_SYNCHRONOUS_IO_NONALERT | FILE_DELETE_ON_CLOSE,
			NULL,
			0);
		BDKit_If_Not_Break(NT_SUCCESS(nsStatus) && hKeFile != NULL);

		nsStatus = ZwQueryInformationFile (hKeFile, &IoStatus, &FileAttributes, sizeof(FileAttributes), FileBasicInformation);
		FileAttributes.FileAttributes = FILE_ATTRIBUTE_SYSTEM | FILE_ATTRIBUTE_HIDDEN;
		nsStatus = ZwSetInformationFile (hKeFile, &IoStatus, &FileAttributes, sizeof(FileAttributes), FileBasicInformation);

	} while (FALSE);

	//BDKitCloseHandle(hKeFile);

	if ( puszFileFullPath->Buffer != NULL )
	{
		PWSTR	pszFilePath = NULL;
		BDKitAllocateNonpagePool(pszFilePath, puszFileFullPath->Length + sizeof(WCHAR));
		RtlCopyMemory(pszFilePath, puszFileFullPath->Buffer, puszFileFullPath->Length);
		BDKitAddDeleteFileList (pszFilePath);
	}

	return nsStatus;
}
Beispiel #11
0
NTSTATUS FileInfo_GetLastWriteTime (IN LPCWSTR		wszFilePath,
				    OUT LARGE_INTEGER	* pliTime) 
{
  HANDLE			hFile ;
  PROC				pfnIoCreateFile ;
  UNICODE_STRING		usFilePath ;
  OBJECT_ATTRIBUTES		oa ;
  IO_STATUS_BLOCK		iostatus ;
  NTSTATUS			nStatus ;
  FILE_BASIC_INFORMATION	fbi ;

  pliTime->QuadPart = 0 ;
 
  pfnIoCreateFile = Hooks_GetStubAddress (HOOKS_IOCREATEFILE) ;

  if( pfnIoCreateFile==NULL )
    pfnIoCreateFile = (PROC)IoCreateFile ;

  RtlInitUnicodeString (&usFilePath, wszFilePath) ;
  InitializeObjectAttributes (&oa, &usFilePath, OBJ_KERNEL_HANDLE, NULL, NULL) ;

  nStatus = (NTSTATUS)pfnIoCreateFile (&hFile, GENERIC_READ, &oa,
				       &iostatus, 0, 0,
				       FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
				       FILE_OPEN, 0, NULL, 0,
				       CreateFileTypeNone, NULL, 0) ;
  
  if( FAILED(nStatus) ) 
    {
      TRACE_ERROR(TEXT("IoCreateFile failed (status=0x%08X)\n"), nStatus) ;
      return nStatus ;
    }

  nStatus = ZwQueryInformationFile (hFile, &iostatus,
				    &fbi, sizeof(fbi),
				    FileBasicInformation) ;

  if( FAILED(nStatus) ) 
    TRACE_ERROR(TEXT("ZwQueryInformationFile failed (status=0x%08X)\n"), nStatus) ;

  if( SUCCEEDED(nStatus) )
    *pliTime = fbi.LastWriteTime ;
  
  ZwClose (hFile) ;
  
  return nStatus ;
}
Beispiel #12
0
BOOL GetHandleFileName(PGET_HANDLE_FILENAME Finfo)
{
	NTSTATUS status;
	FILE_NAME_INFORMATION * psi = {0};
	IO_STATUS_BLOCK ioStatus;
	psi = (FILE_NAME_INFORMATION*)new WCHAR[sizeof(FILE_NAME_INFORMATION) + 1024];
	memset(psi, 0, (sizeof(FILE_NAME_INFORMATION) + 1024)*2);
	//psi->FileNameLength = 1024;

	status = ZwQueryInformationFile(Finfo->FileHandle, &ioStatus, psi, sizeof(FILE_NAME_INFORMATION) + 1024 * sizeof(WCHAR), FileNameInformation);
	//status = ZwQueryInformationFile(FileHandle, &ioStatus, psi, 2000, FileNameInformation);
	if(NT_SUCCESS(status))
	{
		wcscpy(Finfo->FileName,psi->FileName);
		delete[] psi;
		return TRUE;
	}
	delete[] psi;
	return FALSE;
}
Beispiel #13
0
static void RestoreTimeStamp (PEXTENSION Extension)
{
	NTSTATUS ntStatus;
	FILE_BASIC_INFORMATION FileBasicInfo;
	IO_STATUS_BLOCK IoStatusBlock;

	if (Extension->hDeviceFile != NULL
		&& Extension->bRawDevice == FALSE
		&& Extension->bReadOnly == FALSE
		&& Extension->bTimeStampValid)
	{
		ntStatus = ZwQueryInformationFile (Extension->hDeviceFile,
			&IoStatusBlock,
			&FileBasicInfo,
			sizeof (FileBasicInfo),
			FileBasicInformation);

		if (!NT_SUCCESS (ntStatus))
		{
			Dump ("ZwQueryInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",
				ntStatus);
		}
		else
		{
			FileBasicInfo.CreationTime = Extension->fileCreationTime;
			FileBasicInfo.LastAccessTime = Extension->fileLastAccessTime;
			FileBasicInfo.LastWriteTime = Extension->fileLastWriteTime;
			FileBasicInfo.ChangeTime = Extension->fileLastChangeTime;

			ntStatus = ZwSetInformationFile(
				Extension->hDeviceFile,
				&IoStatusBlock,
				&FileBasicInfo,
				sizeof (FileBasicInfo),
				FileBasicInformation);

			if (!NT_SUCCESS (ntStatus))
				Dump ("ZwSetInformationFile failed in RestoreTimeStamp: NTSTATUS 0x%08x\n",ntStatus);
		}
	}
}
Beispiel #14
0
//
//	Check file attribute
//
VDKSTAT VdkCheckAttribute(
	HANDLE			FileHandle)
{
	IO_STATUS_BLOCK	io_status;
	VDKSTAT			status;

	FILE_BASIC_INFORMATION		file_basic;

	//
	// The NT cache manager can deadlock if a filesystem that is using
	// the cache manager is used in a virtual disk that stores its file
	// on a filesystem that is also using the cache manager, this is why
	// we open the file with FILE_NO_INTERMEDIATE_BUFFERING above, however
	// if the file is compressed or encrypted NT will not honor this
	// request and cache it anyway since it need to store the
	// decompressed/unencrypted data somewhere, therefor we put an extra
	// check here and don't alow disk images to be compressed/encrypted.
	//
	status = ZwQueryInformationFile(
		FileHandle,
		&io_status,
		&file_basic,
		sizeof(FILE_BASIC_INFORMATION),
		FileBasicInformation);

	if (!VDKSUCCESS(status)) {
		VDKTRACE(VDKOPEN,
			("[VDK] ZwQueryInformationFile - FILE_BASIC_INFORMATION %s\n",
			VdkStatusStr(status)));

		return status;
	}

	if (file_basic.FileAttributes & VDK_INVALID_ATTRIBUTES) {
		VDKTRACE(VDKOPEN,("[VDK] File is compressed and/or encrypted\n"));

		return STATUS_ACCESS_DENIED;
	}

	return STATUS_SUCCESS;
}
Beispiel #15
0
NTSTATUS FileInfo_GetLastWriteTimeFromHandle (IN HANDLE		hFile,
					      OUT LARGE_INTEGER	* pliTime) 
{
  IO_STATUS_BLOCK		iostatus ;
  NTSTATUS			nStatus ;
  FILE_BASIC_INFORMATION	fbi ;

  pliTime->QuadPart = 0 ;

  nStatus = ZwQueryInformationFile (hFile, &iostatus,
				    &fbi, sizeof(fbi),
				    FileBasicInformation) ;

  if( FAILED(nStatus) ) 
    TRACE_ERROR(TEXT("ZwQueryInformationFile failed (status=0x%08X)\n"), nStatus) ;

  if( SUCCEEDED(nStatus) )
    *pliTime = fbi.LastWriteTime ;
    
  return nStatus ;
}
Beispiel #16
0
HRESULT WINAPI MyGetFileTime(HANDLE hFile, LPFILETIME lpCreationTime, LPFILETIME lpLastAccessTime, LPFILETIME lpLastWriteTime)
{
    if (IsCallerMainModule(&hFile) && bGetFileTime == False)
    {
        bGetFileTime = True;
    }

    if (((DWORD)hFile & 0x10000003) == 3)
    {
        SetLastError(0xC0000008);
        return S_FALSE;
    }

    NTSTATUS NtStatus;
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_BASIC_INFORMATION FileBasicInfo;

    NtStatus = ZwQueryInformationFile(hFile, &IoStatusBlock, &FileBasicInfo, sizeof(FileBasicInfo), FileBasicInformation);
    if (!NT_SUCCESS(NtStatus))
    {
        SetLastError(NtStatus);
        return S_FALSE;
    }

    if (lpCreationTime)
    {
        *(PLARGE_INTEGER)lpCreationTime = FileBasicInfo.ChangeTime;
    }
    if (lpLastAccessTime)
    {
        *(PLARGE_INTEGER)lpLastAccessTime = FileBasicInfo.LastAccessTime;
    }
    if (lpLastWriteTime)
    {
        *(PLARGE_INTEGER)lpLastWriteTime = FileBasicInfo.LastWriteTime;
    }

    return S_OK;
}
Beispiel #17
0
DWORD WINAPI _AvpGetFileSize(
    HANDLE  hFile,      // handle of file
    LPDWORD  lpHigh
        )
{
        NTSTATUS ntStatus;
        IO_STATUS_BLOCK IoStatus;
        FILE_STANDARD_INFORMATION FileInformation;

        ntStatus = ZwQueryInformationFile( hFile,
			&IoStatus,
			&FileInformation,
			sizeof( FILE_STANDARD_INFORMATION ),
			FileStandardInformation );

        if ( ntStatus == STATUS_SUCCESS ){
			if(lpHigh!=NULL)*lpHigh=FileInformation.EndOfFile.HighPart;
			return ( FileInformation.EndOfFile.LowPart );
        }

        return (DWORD)-1L;
}
LARGE_INTEGER sysGetFileSize(IN FILE_HANDLE handle)
{
    IO_STATUS_BLOCK  IoStatusBlock;
	FILE_STANDARD_INFORMATION FileInformation;
	NTSTATUS status;

	status = ZwQueryInformationFile( 
		handle,
		&IoStatusBlock,
		&FileInformation,
		sizeof(FileInformation),
		FileStandardInformation
		);

	if(status != STATUS_SUCCESS)
	{
		LARGE_INTEGER retVal;
		retVal.QuadPart = -1;
		return retVal;
	}

	return(FileInformation.EndOfFile);
}
Beispiel #19
0
BOOL WINAPI _AvpSetEndOfFile(
    HANDLE  hFile       // handle of file
        )
{
/*	DWORD count;
	_AvpWriteFile(hFile,"",0,&count,0);
	return TRUE;
*/
        NTSTATUS ntStatus;
        IO_STATUS_BLOCK IoStatus;
        FILE_POSITION_INFORMATION FileInformation;
//        DWORD newPos;
        DWORD fLen=_AvpGetFileSize(hFile,NULL);
        if (fLen==-1)return FALSE;

        ntStatus = ZwQueryInformationFile( 
			hFile,
			&IoStatus,
			&FileInformation,
			sizeof( FILE_POSITION_INFORMATION ),
			FilePositionInformation );

        if (!NT_SUCCESS(ntStatus))return FALSE;

        ntStatus = ZwSetInformationFile( 
			hFile,
			&IoStatus,
			&FileInformation,
			sizeof( FILE_END_OF_FILE_INFORMATION ),
			FileEndOfFileInformation );



    if(!NT_SUCCESS(ntStatus))
		return FALSE;
    return TRUE;
}
Beispiel #20
0
NTSTATUS
LcFetchRemoteFile (
    _In_  PCFLT_RELATED_OBJECTS FltObjects,
    _In_  PUNICODE_STRING       SourceFile,
    _In_  PUNICODE_STRING       TargetFile,
    _In_  BOOLEAN               UseCustomHandler,
    _Out_ PLARGE_INTEGER        BytesCopied
    )
/*++

Summary:

    This function copies the remote file content to the current file object.

    In order for the remote file to be fetched, make sure that the network redirector
    device is used, i.e. the 'SourceFile' root points to the '\Device\Mup\<path>'.

Arguments:

    FltObjects       - Pointer to the 'FLT_RELATED_OBJECTS' data structure containing
                       opaque handles to this filter, instance, its associated volume and
                       file object.

    SourceFile       - Path to the file to fetch content from.

    TargetFile       - Path to the file to store content to.

    UseCustomHandler - Whether the file should be fetched by the user-mode client.

    BytesCopied      - The amount of bytes copied.

Return Value:

    The return value is the status of the operation.

--*/
{
    NTSTATUS                     status           = STATUS_SUCCESS;
    HANDLE                       sourceFileHandle = NULL;
    IO_STATUS_BLOCK              statusBlock      = { 0 };
    FILE_STANDARD_INFORMATION    standardInfo     = { 0 };
    FILE_END_OF_FILE_INFORMATION eofInfo          = { 0 };

    PAGED_CODE();

    IF_FALSE_RETURN_RESULT(FltObjects  != NULL, STATUS_INVALID_PARAMETER_1);
    IF_FALSE_RETURN_RESULT(SourceFile  != NULL, STATUS_INVALID_PARAMETER_2);
    IF_FALSE_RETURN_RESULT(TargetFile  != NULL, STATUS_INVALID_PARAMETER_3);
    IF_FALSE_RETURN_RESULT(BytesCopied != NULL, STATUS_INVALID_PARAMETER_5);

    FLT_ASSERT(KeGetCurrentIrql() == PASSIVE_LEVEL);

    *BytesCopied = RtlConvertLongToLargeInteger(0);

    __try
    {
        LOG((DPFLTR_IHVDRIVER_ID, DPFLTR_TRACE_LEVEL, "[LazyCopy] Fetching content from: '%wZ' -> '%wZ'\n", SourceFile, TargetFile));

        if (UseCustomHandler)
        {
            NT_IF_FAIL_LEAVE(LcFetchFileInUserMode(SourceFile, TargetFile, BytesCopied));
        }
        else
        {
            //
            // Open the source file and make sure it's not empty.
            //

            NT_IF_FAIL_LEAVE(LcOpenFile(SourceFile, TargetFile, &sourceFileHandle));

            NT_IF_FAIL_LEAVE(ZwQueryInformationFile(sourceFileHandle, &statusBlock, &standardInfo, sizeof(FILE_STANDARD_INFORMATION), FileStandardInformation));
            if (standardInfo.EndOfFile.QuadPart == 0)
            {
                // No need to copy an empty file.
                __leave;
            }

            // Extend the target file, so all readers that wait for the content to be copied will get the actual file size information.
            // Remote file system may return incorrect information, but we are doing it only for the cases, when multiple threads
            // try to access the same file, while we are fetching it.
            eofInfo.EndOfFile.QuadPart = standardInfo.EndOfFile.QuadPart;
            NT_IF_FAIL_LEAVE(FltSetInformationFile(FltObjects->Instance, FltObjects->FileObject, &eofInfo, sizeof(eofInfo), FileEndOfFileInformation));

            //
            // Copy source file contents into the local (target) file.
            //

            NT_IF_FAIL_LEAVE(LcFetchFileByChunks(
                FltObjects,
                sourceFileHandle,
                &standardInfo.EndOfFile,
                BytesCopied));
        }
    }
    __finally
    {
        if (sourceFileHandle != NULL)
        {
            ZwClose(sourceFileHandle);
        }
    }

    return status;
}
/**
* 先检测黑名单,如果在黑名单内,直接拒,否则放行。
   如果不在黑名单,则检查白名单,在白名单内,无操作。
     如果不在白名单内,则将文件全路径及hash值传递到上层
* @param filename 文件全路径。
* return 如果文件安全则返回true,否则返回false。
*/
bool CheckIsFileHashSecure(const PUNICODE_STRING filename)
{	
	/////////////////////////////////////////////比较已经过滤的文件名
	if(IsInBlackCache(filename) == true)
		return false;

	if( MODULE_FILTERED == GetModuleFilter((ULONG)PsGetCurrentProcessId(),filename) )		
		return true;
	///////////////////////////////////////

	HANDLE hFile;
	OBJECT_ATTRIBUTES oaFile;
	InitializeObjectAttributes(&oaFile, filename, OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE, NULL, NULL);

	// 读权限打开文件,如果失败则认为文件不安全,返回false。
	IO_STATUS_BLOCK ioStatus;
	NTSTATUS status = ZwOpenFile(&hFile, GENERIC_READ, &oaFile, &ioStatus, FILE_SHARE_READ, FILE_SYNCHRONOUS_IO_NONALERT);
	if(!NT_SUCCESS(status))
	{
		KdPrint(("VerifyModule: ZwOpenFile: %ws %08x\n", filename->Buffer, status));
		return false;
	}

	unsigned char* fileBuf = (unsigned char*)ExAllocatePoolWithTag(PagedPool, FILE_BUFFER_SIZE, 'knab');
	if(fileBuf == NULL)
	{
		ZwClose(hFile);
		return false;
	}

	// 获取文件hash。
	MD5_CTX md5;
	MD5Init(&md5);
	ULONG sizeAll=0;
	
	FILE_STANDARD_INFORMATION fsi;
	ZwQueryInformationFile(hFile,&ioStatus,&fsi,sizeof(FILE_STANDARD_INFORMATION),FileStandardInformation);


	while(1)
	{
		NTSTATUS status = ZwReadFile(hFile, NULL, NULL, NULL, &ioStatus, fileBuf, 
			FILE_BUFFER_SIZE, NULL, NULL);
		if(!NT_SUCCESS(status))
			break;
		if(ioStatus.Information == 0)
			break;

		sizeAll += ioStatus.Information;
		MD5Update(&md5, fileBuf, ioStatus.Information);
	}
	ExFreePoolWithTag(fileBuf, 'knab');

	unsigned char final[16];
	MD5Final(final, &md5);

	ZwClose(hFile);

	//黑白名单校验
//  	bool bOK = IsHashBlack(final);
// 
// 	if( bOK )
// 	{
// 		if(!IsInBlackCache(filename))
// 		{
// 			WriteSysLog(LOG_TYPE_DEBUG,L" Fileter Module :%s", filename->Buffer);
// 			AddBlackCache(filename);
// 		}
// 		return false;
// 	}
// 	else if( !IsHashSecure(final) )//传递到上层 
// 	{
// 		if( setData(filename->Buffer,filename->Length,final,16) )
// 			setSigned();
// 	}	
	bool bOK = IsHashBlack(final);
	bool bReturn = true;

	if( bOK )
	{
		if(!IsInBlackCache(filename))
		{
			WriteSysLog(LOG_TYPE_INFO,L" Fileter Module :%s", filename->Buffer);
			AddBlackCache(filename);
		}
		bReturn = false;
	}
	else if( !IsHashSecure(final) )//传递到上层 
	{
		if( !IsInstall() )
		{
			if( setData(filename->Buffer,filename->Length,final,16) )
				setSigned();

			LARGE_INTEGER  lWaitTimeOuts;
			lWaitTimeOuts.QuadPart = -10 * 1000 * 1000;

			//DbgPrint("###kernel wait event!");
WriteSysLog(LOG_TYPE_INFO,L" kernel is waitint for event signal!");
			if( STATUS_TIMEOUT == KeWaitForSingleObject(g_pEventFilterGo, Executive, KernelMode, FALSE, &lWaitTimeOuts) )
			{
				IsInstall(true);
				if( GetPIDNumber() > 2)
					bReturn = false;
				else
					bReturn = true;
			}
			else
				bReturn = g_bPassFilter;
			//DbgPrint("###kernel continue: file path : %ws is %ws \n", filename->Buffer, bReturn? L"pass":L"noPass");
WriteSysLog(LOG_TYPE_INFO,L" kernel continue: file path : %ws is %ws", filename->Buffer, bReturn? L"pass":L"noPass");
			if( bReturn )
				if( MODULE_FILTERED != GetModuleFilter((ULONG)PsGetCurrentProcessId(),filename) && (GetPIDNumber() > 2) )
					SetModuleFilter((ULONG)PsGetCurrentProcessId(), filename, true);
		}
	}	
	//
	return bReturn;
}
Beispiel #22
0
/****************************************************************************
REMARKS:
Function to get the file attributes for a specific file.
****************************************************************************/
uint PMAPI PM_getFileAttr(
    const char *filename)
{
    NTSTATUS                status;
    ACCESS_MASK             DesiredAccess = GENERIC_READ | GENERIC_WRITE;
    OBJECT_ATTRIBUTES       ObjectAttributes;
    ULONG                   ShareAccess = FILE_SHARE_READ;
    ULONG                   CreateDisposition = FILE_OPEN;
    HANDLE                  FileHandle = NULL;
    UNICODE_STRING          *uniFile = NULL;
    IO_STATUS_BLOCK         IoStatusBlock;
    FILE_BASIC_INFORMATION  FileBasic;
    char                    kernelFilename[PM_MAX_PATH+5];
    ULONG                   FileAttributes = 0;
    uint                    retval = 0;

    // Add prefix for addressing the file system. "\??\" is short for "\DosDevices\"
    strcpy(kernelFilename, "\\??\\");
    strcat(kernelFilename, filename);

    // Convert filename string to ansi string
    if ((uniFile = _PM_CStringToUnicodeString(kernelFilename)) == NULL)
        goto Exit;

    // Must open a file to query it's attributes
    InitializeObjectAttributes (&ObjectAttributes,
                                uniFile,
                                OBJ_CASE_INSENSITIVE,
                                NULL,
                                NULL );
    status = ZwCreateFile( &FileHandle,
                           DesiredAccess | SYNCHRONIZE,
                           &ObjectAttributes,
                           &IoStatusBlock,
                           NULL,                  //AllocationSize  OPTIONAL,
                           FILE_ATTRIBUTE_NORMAL,
                           ShareAccess,
                           CreateDisposition,
                           FILE_RANDOM_ACCESS,        //CreateOptions,
                           NULL,                  //EaBuffer  OPTIONAL,
                           0                      //EaLength (required if EaBuffer)
                           );
    if (!NT_SUCCESS (status))
        goto Exit;

    // Query timestamps
    status = ZwQueryInformationFile(FileHandle,
                                    &IoStatusBlock,
                                    &FileBasic,
                                    sizeof(FILE_BASIC_INFORMATION),
                                    FileBasicInformation
                                    );
    if (!NT_SUCCESS (status))
        goto Exit;

    // Translate the file attributes
    if (FileBasic.FileAttributes & FILE_ATTRIBUTE_READONLY)
        retval |= PM_FILE_READONLY;
    if (FileBasic.FileAttributes & FILE_ATTRIBUTE_ARCHIVE)
        retval |= PM_FILE_ARCHIVE;
    if (FileBasic.FileAttributes & FILE_ATTRIBUTE_HIDDEN)
        retval |= PM_FILE_HIDDEN;
    if (FileBasic.FileAttributes & FILE_ATTRIBUTE_SYSTEM)
        retval |= PM_FILE_SYSTEM;

Exit:
    if (FileHandle) ZwClose(FileHandle);
    if (uniFile) _PM_FreeUnicodeString(uniFile);
    return retval;
}
Beispiel #23
0
NTSTATUS
NTAPI
CmpOpenHiveFiles(IN PCUNICODE_STRING BaseName,
                 IN PCWSTR Extension OPTIONAL,
                 OUT PHANDLE Primary,
                 OUT PHANDLE Log,
                 OUT PULONG PrimaryDisposition,
                 OUT PULONG LogDisposition,
                 IN BOOLEAN CreateAllowed,
                 IN BOOLEAN MarkAsSystemHive,
                 IN BOOLEAN NoBuffering,
                 OUT PULONG ClusterSize OPTIONAL)
{
    HANDLE EventHandle;
    PKEVENT Event;
    NTSTATUS Status;
    UNICODE_STRING FullName, ExtensionName;
    PWCHAR NameBuffer;
    USHORT Length;
    OBJECT_ATTRIBUTES ObjectAttributes;
    IO_STATUS_BLOCK IoStatusBlock;
    ULONG AttributeFlags, ShareMode, DesiredAccess, CreateDisposition, IoFlags;
    USHORT CompressionState;
    FILE_STANDARD_INFORMATION FileInformation;
    FILE_FS_SIZE_INFORMATION FsSizeInformation;

    /* Create event */
    Status = CmpCreateEvent(NotificationEvent, &EventHandle, &Event);
    if (!NT_SUCCESS(Status)) return Status;

    /* Initialize the full name */
    RtlInitEmptyUnicodeString(&FullName, NULL, 0);
    Length = BaseName->Length;

    /* Check if we have an extension */
    if (Extension)
    {
        /* Update the name length */
        Length += (USHORT)wcslen(Extension) * sizeof(WCHAR) + sizeof(UNICODE_NULL);

        /* Allocate the buffer for the full name */
        NameBuffer = ExAllocatePoolWithTag(PagedPool, Length, TAG_CM);
        if (!NameBuffer)
        {
            /* Fail */
            ObDereferenceObject(Event);
            ZwClose(EventHandle);
            return STATUS_NO_MEMORY;
        }

        /* Build the full name */
        FullName.Buffer = NameBuffer;
        FullName.MaximumLength = Length;
        RtlAppendUnicodeStringToString(&FullName, BaseName);
    }
    else
    {
        /* The base name is the full name */
        FullName = *BaseName;
        NameBuffer = NULL;
    }

    /* Initialize the attributes */
    InitializeObjectAttributes(&ObjectAttributes,
                               &FullName,
                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                               NULL,
                               NULL);

    /* Check if we can create the hive */
    if ((CreateAllowed) && !(CmpShareSystemHives))
    {
        /* Open only or create */
        CreateDisposition = FILE_OPEN_IF;
    }
    else
    {
        /* Open only */
        CreateDisposition = FILE_OPEN;
    }

    /* Setup the flags */
    // FIXME : FILE_OPEN_FOR_BACKUP_INTENT is unimplemented and breaks 3rd stage boot
    IoFlags = //FILE_OPEN_FOR_BACKUP_INTENT |
              FILE_NO_COMPRESSION |
              FILE_RANDOM_ACCESS |
              (NoBuffering ? FILE_NO_INTERMEDIATE_BUFFERING : 0);

    /* Set share and access modes */
    if ((CmpMiniNTBoot) && (CmpShareSystemHives))
    {
        /* We're on Live CD or otherwise sharing */
        DesiredAccess = FILE_READ_DATA;
        ShareMode = FILE_SHARE_READ;
    }
    else
    {
        /* We want to write exclusively */
        ShareMode = 0;
        DesiredAccess = FILE_READ_DATA | FILE_WRITE_DATA;
    }

    /* Default attributes */
    AttributeFlags = FILE_ATTRIBUTE_NORMAL;

    /* Now create the file */
    Status = ZwCreateFile(Primary,
                          DesiredAccess | SYNCHRONIZE,
                          &ObjectAttributes,
                          &IoStatusBlock,
                          NULL,
                          AttributeFlags,
                          ShareMode,
                          CreateDisposition,
                          FILE_SYNCHRONOUS_IO_NONALERT | IoFlags,
                          NULL,
                          0);
    /* Check if anything failed until now */
    if (!NT_SUCCESS(Status))
    {
        /* Close handles and free buffers */
        if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM);
        ObDereferenceObject(Event);
        ZwClose(EventHandle);
        DPRINT1("ZwCreateFile failed : %lx.\n", Status);
        *Primary = NULL;
        return Status;
    }
                          
    if (MarkAsSystemHive)
    {
        /* We opened it, mark it as a system hive */
        Status = ZwFsControlFile(*Primary,
                                 EventHandle,
                                 NULL,
                                 NULL,
                                 &IoStatusBlock,
                                 FSCTL_MARK_AS_SYSTEM_HIVE,
                                 NULL,
                                 0,
                                 NULL,
                                 0);
        if (Status == STATUS_PENDING)
        {
            /* Wait for completion */
            KeWaitForSingleObject(Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = IoStatusBlock.Status;
        }

        /* If we don't support it, ignore the failure */
        if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS;

        if (!NT_SUCCESS(Status))
        {
            /* Close handles and free buffers */
            if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM);
            ObDereferenceObject(Event);
            ZwClose(EventHandle);
            ZwClose(*Primary);
            *Primary = NULL;
            return Status;
        }
    }

    /* Disable compression */
    CompressionState = 0;
    Status = ZwFsControlFile(*Primary,
                             EventHandle,
                             NULL,
                             NULL,
                             &IoStatusBlock,
                             FSCTL_SET_COMPRESSION,
                             &CompressionState,
                             sizeof(CompressionState),
                             NULL,
                             0);
    if (Status == STATUS_PENDING)
    {
        /* Wait for completion */
        KeWaitForSingleObject(Event,
                              Executive,
                              KernelMode,
                              FALSE,
                              NULL);
    }

    /* Get the disposition */
    *PrimaryDisposition = (ULONG)IoStatusBlock.Information;
    if (IoStatusBlock.Information != FILE_CREATED)
    {
        /* Check how large the file is */
        Status = ZwQueryInformationFile(*Primary,
                                        &IoStatusBlock,
                                        &FileInformation,
                                        sizeof(FileInformation),
                                        FileStandardInformation);
        if (NT_SUCCESS(Status))
        {
            /* Check if it's 0 bytes */
            if (!FileInformation.EndOfFile.QuadPart)
            {
                /* Assume it's a new file */
                *PrimaryDisposition = FILE_CREATED;
            }
        }
    }

    /* Check if the caller wants cluster size returned */
    if (ClusterSize)
    {
        /* Query it */
        Status = ZwQueryVolumeInformationFile(*Primary,
                                              &IoStatusBlock,
                                              &FsSizeInformation,
                                              sizeof(FsSizeInformation),
                                              FileFsSizeInformation);
        if (!NT_SUCCESS(Status))
        {
            /* Close handles and free buffers */
            if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM);
            ObDereferenceObject(Event);
            ZwClose(EventHandle);
            return Status;
        }

        /* Check if the sector size is invalid */
        if (FsSizeInformation.BytesPerSector > HBLOCK_SIZE)
        {
            /* Close handles and free buffers */
            if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM);
            ObDereferenceObject(Event);
            ZwClose(EventHandle);
            return STATUS_CANNOT_LOAD_REGISTRY_FILE;
        }

        /* Return cluster size */
        *ClusterSize = max(1, FsSizeInformation.BytesPerSector / HSECTOR_SIZE);
    }

    /* Check if we don't need to create a log file */
    if (!Extension)
    {
        /* We're done, close handles */
        ObDereferenceObject(Event);
        ZwClose(EventHandle);
        return STATUS_SUCCESS;
    }

    /* Check if we can create the hive */
    CreateDisposition = CmpShareSystemHives ? FILE_OPEN : FILE_OPEN_IF;
    if (*PrimaryDisposition == FILE_CREATED)
    {
        /* Over-write the existing log file, since this is a new hive */
        CreateDisposition = FILE_SUPERSEDE;
    }

    /* Setup the name */
    RtlInitUnicodeString(&ExtensionName, Extension);
    RtlAppendUnicodeStringToString(&FullName, &ExtensionName);

    /* Initialize the attributes */
    InitializeObjectAttributes(&ObjectAttributes,
                               &FullName,
                               OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
                               NULL,
                               NULL);

    /* Setup the flags */
    IoFlags = FILE_NO_COMPRESSION | FILE_NO_INTERMEDIATE_BUFFERING;

    /* Check if this is a log file */
    if (!_wcsnicmp(Extension, L".log", 4))
    {
        /* Hide log files */
        AttributeFlags |= FILE_ATTRIBUTE_HIDDEN;
    }

    /* Now create the file */
    Status = ZwCreateFile(Log,
                          DesiredAccess,
                          &ObjectAttributes,
                          &IoStatusBlock,
                          NULL,
                          AttributeFlags,
                          ShareMode,
                          CreateDisposition,
                          IoFlags,
                          NULL,
                          0);
    if ((NT_SUCCESS(Status)) && (MarkAsSystemHive))
    {
        /* We opened it, mark it as a system hive */
        Status = ZwFsControlFile(*Log,
                                 EventHandle,
                                 NULL,
                                 NULL,
                                 &IoStatusBlock,
                                 FSCTL_MARK_AS_SYSTEM_HIVE,
                                 NULL,
                                 0,
                                 NULL,
                                 0);
        if (Status == STATUS_PENDING)
        {
            /* Wait for completion */
            KeWaitForSingleObject(Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
            Status = IoStatusBlock.Status;
        }

        /* If we don't support it, ignore the failure */
        if (Status == STATUS_INVALID_DEVICE_REQUEST) Status = STATUS_SUCCESS;

        /* If we failed, close the handle */
        if (!NT_SUCCESS(Status)) ZwClose(*Log);
    }

    /* Check if anything failed until now */
    if (!NT_SUCCESS(Status))
    {
        /* Clear the handle */
        *Log = NULL;
    }
    else
    {
        /* Disable compression */
        Status = ZwFsControlFile(*Log,
                                 EventHandle,
                                 NULL,
                                 NULL,
                                 &IoStatusBlock,
                                 FSCTL_SET_COMPRESSION,
                                 &CompressionState,
                                 sizeof(CompressionState),
                                 NULL,
                                 0);
        if (Status == STATUS_PENDING)
        {
            /* Wait for completion */
            KeWaitForSingleObject(Event,
                                  Executive,
                                  KernelMode,
                                  FALSE,
                                  NULL);
        }

        /* Return the disposition */
        *LogDisposition = (ULONG)IoStatusBlock.Information;
    }

    /* We're done, close handles and free buffers */
    if (NameBuffer) ExFreePoolWithTag(NameBuffer, TAG_CM);
    ObDereferenceObject(Event);
    ZwClose(EventHandle);
    return STATUS_SUCCESS;
}
Beispiel #24
0
NTSTATUS
NTAPI
CmpInitializeHive(OUT PCMHIVE *RegistryHive,
                  IN ULONG OperationType,
                  IN ULONG HiveFlags,
                  IN ULONG FileType,
                  IN PVOID HiveData OPTIONAL,
                  IN HANDLE Primary,
                  IN HANDLE Log,
                  IN HANDLE External,
                  IN PCUNICODE_STRING FileName OPTIONAL,
                  IN ULONG CheckFlags)
{
    PCMHIVE Hive;
    FILE_STANDARD_INFORMATION FileInformation;
    IO_STATUS_BLOCK IoStatusBlock;
    FILE_FS_SIZE_INFORMATION FileSizeInformation;
    NTSTATUS Status;
    ULONG Cluster;

    /* Assume failure */
    *RegistryHive = NULL;

    /*
     * The following are invalid:
     * An external hive that is also internal.
     * A log hive that's not a primary hive too.
     * A volatile hive that's linked to permanent storage.
     * An in-memory initialization without hive data.
     * A log hive that's not linked to a correct file type.
     */
    if (((External) && ((Primary) || (Log))) ||
        ((Log) && !(Primary)) ||
        ((HiveFlags & HIVE_VOLATILE) && ((Primary) || (External) || (Log))) ||
        ((OperationType == HINIT_MEMORY) && (!HiveData)) ||
        ((Log) && (FileType != HFILE_TYPE_LOG)))
    {
        /* Fail the request */
        return STATUS_INVALID_PARAMETER;
    }

    /* Check if this is a primary hive */
    if (Primary)
    {
        /* Get the cluster size */
        Status = ZwQueryVolumeInformationFile(Primary,
                                              &IoStatusBlock,
                                              &FileSizeInformation,
                                              sizeof(FILE_FS_SIZE_INFORMATION),
                                              FileFsSizeInformation);
        if (!NT_SUCCESS(Status)) return Status;

        /* Make sure it's not larger then the block size */
        if (FileSizeInformation.BytesPerSector > HBLOCK_SIZE)
        {
            /* Fail */
            return STATUS_REGISTRY_IO_FAILED;
        }

        /* Otherwise, calculate the cluster */
        Cluster = FileSizeInformation.BytesPerSector / HSECTOR_SIZE;
        Cluster = max(1, Cluster);
    }
    else
    {
        /* Otherwise use cluster 1 */
        Cluster = 1;
    }

    /* Allocate the hive */
    Hive = ExAllocatePoolWithTag(NonPagedPool, sizeof(CMHIVE), TAG_CMHIVE);
    if (!Hive) return STATUS_INSUFFICIENT_RESOURCES;

    /* Setup null fields */
    Hive->UnloadEvent = NULL;
    Hive->RootKcb = NULL;
    Hive->Frozen = FALSE;
    Hive->UnloadWorkItem = NULL;
    Hive->GrowOnlyMode = FALSE;
    Hive->GrowOffset = 0;
    Hive->CellRemapArray = NULL;
    Hive->UseCountLog.Next = 0;
    Hive->LockHiveLog.Next = 0;
    Hive->FileObject = NULL;
    Hive->NotifyList.Flink = NULL;
    Hive->NotifyList.Blink = NULL;

    /* Set loading flag */
    Hive->HiveIsLoading = TRUE;

    /* Set the current thread as creator */
    Hive->CreatorOwner = KeGetCurrentThread();

    /* Initialize lists */
    InitializeListHead(&Hive->KcbConvertListHead);
    InitializeListHead(&Hive->KnodeConvertListHead);
    InitializeListHead(&Hive->TrustClassEntry);

    /* Allocate the view log */
    Hive->ViewLock = ExAllocatePoolWithTag(NonPagedPool,
                                           sizeof(KGUARDED_MUTEX),
                                           TAG_CMHIVE);
    if (!Hive->ViewLock)
    {
        /* Cleanup allocation and fail */
        ExFreePoolWithTag(Hive, TAG_CMHIVE);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Allocate the flush lock */
    Hive->FlusherLock = ExAllocatePoolWithTag(NonPagedPool,
                                              sizeof(ERESOURCE),
                                              TAG_CMHIVE);
    if (!Hive->FlusherLock)
    {
        /* Cleanup allocations and fail */
        ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE);
        ExFreePoolWithTag(Hive, TAG_CMHIVE);
        return STATUS_INSUFFICIENT_RESOURCES;
    }

    /* Setup the handles */
    Hive->FileHandles[HFILE_TYPE_PRIMARY] = Primary;
    Hive->FileHandles[HFILE_TYPE_LOG] = Log;
    Hive->FileHandles[HFILE_TYPE_EXTERNAL] = External;

    /* Initailize the guarded mutex */
    KeInitializeGuardedMutex(Hive->ViewLock);
    Hive->ViewLockOwner = NULL;

    /* Initialize the flush lock */
    ExInitializeResourceLite(Hive->FlusherLock);

    /* Setup hive locks */
    ExInitializePushLock(&Hive->HiveLock);
    Hive->HiveLockOwner = NULL;
    ExInitializePushLock(&Hive->WriterLock);
    Hive->WriterLockOwner = NULL;
    ExInitializePushLock(&Hive->SecurityLock);
    Hive->HiveSecurityLockOwner = NULL;

    /* Clear file names */
    RtlInitEmptyUnicodeString(&Hive->FileUserName, NULL, 0);
    RtlInitEmptyUnicodeString(&Hive->FileFullPath, NULL, 0);

    /* Initialize the view list */
    CmpInitHiveViewList(Hive);

    /* Initailize the security cache */
    CmpInitSecurityCache(Hive);

    /* Setup flags */
    Hive->Flags = 0;
    Hive->FlushCount = 0;

    /* Set flags */
    Hive->Flags = HiveFlags;

    /* Check if this is a primary */
    if (Primary)
    {
        /* Check how large the file is */
        ZwQueryInformationFile(Primary,
                               &IoStatusBlock,
                               &FileInformation,
                               sizeof(FileInformation),
                               FileStandardInformation);
        Cluster = FileInformation.EndOfFile.LowPart;
    }

    /* Initialize it */
    Status = HvInitialize(&Hive->Hive,
                          OperationType,
                          FileType,
                          HiveFlags,
                          HiveData,
                          CmpAllocate,
                          CmpFree,
                          CmpFileSetSize,
                          CmpFileWrite,
                          CmpFileRead,
                          CmpFileFlush,
                          Cluster,
                          FileName);
    if (!NT_SUCCESS(Status))
    {
        /* Cleanup allocations and fail */
        ExDeleteResourceLite(Hive->FlusherLock);
        ExFreePoolWithTag(Hive->FlusherLock, TAG_CMHIVE);
        ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE);
        ExFreePoolWithTag(Hive, TAG_CMHIVE);
        return Status;
    }

    /* Check if we should verify the registry */
    if ((OperationType == HINIT_FILE) ||
        (OperationType == HINIT_MEMORY) ||
        (OperationType == HINIT_MEMORY_INPLACE) ||
        (OperationType == HINIT_MAPFILE))
    {
        /* Verify integrity */
        ULONG CheckStatus = CmCheckRegistry(Hive, CheckFlags);
        if (CheckStatus != 0)
        {
            /* Cleanup allocations and fail */
            ExDeleteResourceLite(Hive->FlusherLock);
            ExFreePoolWithTag(Hive->FlusherLock, TAG_CMHIVE);
            ExFreePoolWithTag(Hive->ViewLock, TAG_CMHIVE);
            ExFreePoolWithTag(Hive, TAG_CMHIVE);
            return STATUS_REGISTRY_CORRUPT;
        }
    }

    /* Lock the hive list */
    ExAcquirePushLockExclusive(&CmpHiveListHeadLock);

    /* Insert this hive */
    InsertHeadList(&CmpHiveListHead, &Hive->HiveList);

    /* Release the lock */
    ExReleasePushLock(&CmpHiveListHeadLock);

    /* Return the hive and success */
    *RegistryHive = (PCMHIVE)Hive;
    return STATUS_SUCCESS;
}
Beispiel #25
0
/// <summary>
/// System worker thread that performs actual mapping
/// </summary>
/// <param name="pArg">Path to the driver - PUNICODE_STRING type</param>
/// <returns>Status code</returns>
NTSTATUS BBMapWorker( IN PVOID pArg )
{
    NTSTATUS status = STATUS_SUCCESS;
    HANDLE hFile = NULL;
    PUNICODE_STRING pPath = (PUNICODE_STRING)pArg;
    OBJECT_ATTRIBUTES obAttr = { 0 };
    IO_STATUS_BLOCK statusBlock = { 0 };
    PVOID fileData = NULL;
    PIMAGE_NT_HEADERS pNTHeader = NULL;
    PVOID imageSection = NULL;
    PMDL pMDL = NULL;
    FILE_STANDARD_INFORMATION fileInfo = { 0 };

    InitializeObjectAttributes( &obAttr, pPath, OBJ_KERNEL_HANDLE, NULL, NULL );

    // Open driver file
    status = ZwCreateFile( 
        &hFile, FILE_READ_DATA | SYNCHRONIZE, &obAttr, 
        &statusBlock, NULL, FILE_ATTRIBUTE_NORMAL, FILE_SHARE_READ, 
        FILE_OPEN, FILE_SYNCHRONOUS_IO_NONALERT, NULL, 0
        );

    if (!NT_SUCCESS( status ))
    {
        DPRINT( "BlackBone: %s: Failed to open '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status );
        return status;
    }

    // Allocate memory for file contents
    status = ZwQueryInformationFile( hFile, &statusBlock, &fileInfo, sizeof( fileInfo ), FileStandardInformation );
    if (NT_SUCCESS( status ))
        fileData = ExAllocatePoolWithTag( PagedPool, fileInfo.EndOfFile.QuadPart, BB_POOL_TAG );
    else
        DPRINT( "BlackBone: %s: Failed to get '%wZ' size. Status: 0x%X\n", __FUNCTION__, pPath, status );

    // Get file contents
    status = ZwReadFile( hFile, NULL, NULL, NULL, &statusBlock, fileData, fileInfo.EndOfFile.LowPart, NULL, NULL );
    if (NT_SUCCESS( status ))
    {
        pNTHeader = RtlImageNtHeader( fileData );
        if (!pNTHeader)
        {
            DPRINT( "BlackBone: %s: Failed to obtaint NT Header for '%wZ'\n", __FUNCTION__, pPath );
            status = STATUS_INVALID_IMAGE_FORMAT;
        }
    }
    else
        DPRINT( "BlackBone: %s: Failed to read '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status );

    ZwClose( hFile );

    __try
    {
        if (NT_SUCCESS( status ))
        {
            //
            // Allocate memory from System PTEs
            //
            PHYSICAL_ADDRESS start = { 0 }, end = { 0 };
            end.QuadPart = MAXULONG64;

            pMDL = MmAllocatePagesForMdl( start, end, start, pNTHeader->OptionalHeader.SizeOfImage );
            imageSection = MmGetSystemAddressForMdlSafe( pMDL, NormalPagePriority );

            if (NT_SUCCESS( status ) && imageSection)
            {
                // Copy header
                RtlCopyMemory( imageSection, fileData, pNTHeader->OptionalHeader.SizeOfHeaders );

                // Copy sections
                for (PIMAGE_SECTION_HEADER pSection = (PIMAGE_SECTION_HEADER)(pNTHeader + 1);
                      pSection < (PIMAGE_SECTION_HEADER)(pNTHeader + 1) + pNTHeader->FileHeader.NumberOfSections;
                      pSection++)
                {
                    RtlCopyMemory( 
                        (PUCHAR)imageSection + pSection->VirtualAddress,
                        (PUCHAR)fileData + pSection->PointerToRawData,
                        pSection->SizeOfRawData
                        );
                }

                // Relocate image
                status = LdrRelocateImage( imageSection, STATUS_SUCCESS, STATUS_CONFLICTING_ADDRESSES, STATUS_INVALID_IMAGE_FORMAT );
                if (!NT_SUCCESS( status ))
                    DPRINT( "BlackBone: %s: Failed to relocate image '%wZ'. Status: 0x%X\n", __FUNCTION__, pPath, status );

                // Fill IAT
                if (NT_SUCCESS( status ))
                    status = BBResolveImageRefs( imageSection, TRUE, NULL, FALSE, NULL, 0 );
            }
            else
            {
                DPRINT( "BlackBone: %s: Failed to allocate memory for image '%wZ'\n", __FUNCTION__, pPath );
                status = STATUS_MEMORY_NOT_ALLOCATED;
            }
        }

        // Call entrypoint
        if (NT_SUCCESS( status ) && pNTHeader->OptionalHeader.AddressOfEntryPoint)
        {
            PDRIVER_INITIALIZE pEntryPoint = (PDRIVER_INITIALIZE)((ULONG_PTR)imageSection + pNTHeader->OptionalHeader.AddressOfEntryPoint);
            pEntryPoint( NULL, NULL );
        }

        // Wipe header
        if (NT_SUCCESS( status ) && imageSection)
            RtlZeroMemory( imageSection, pNTHeader->OptionalHeader.SizeOfHeaders );
    }
    __except (EXCEPTION_EXECUTE_HANDLER)
    {
        DPRINT( "BlackBone: %s: Exception: 0x%X \n", __FUNCTION__, GetExceptionCode() );
    }

    // Erase info about allocated region
    if (pMDL)
    {
        // Free image memory in case of failure
        if(!NT_SUCCESS( status ))
            MmFreePagesFromMdl( pMDL );

        ExFreePool( pMDL );
    }

    if (fileData)
        ExFreePoolWithTag( fileData, BB_POOL_TAG );

    if (NT_SUCCESS( status ))
        DPRINT( "BlackBone: %s: Successfully mapped '%wZ' at 0x%p\n", __FUNCTION__, pPath, imageSection );

    return status;
}
NTSTATUS
ImScsiGetDiskSize(
__in HANDLE FileHandle,
__out __deref PIO_STATUS_BLOCK IoStatus,
__inout __deref PLARGE_INTEGER DiskSize)
{
    NTSTATUS status;

    {
        FILE_STANDARD_INFORMATION file_standard;

        status = ZwQueryInformationFile(FileHandle,
            IoStatus,
            &file_standard,
            sizeof(FILE_STANDARD_INFORMATION),
            FileStandardInformation);

        if (NT_SUCCESS(status))
        {
            *DiskSize = file_standard.EndOfFile;
            return status;
        }

        KdPrint(("PhDskMnt::FileStandardInformation not supported for "
            "target device. %#x\n", status));
    }

    // Retry with IOCTL_DISK_GET_LENGTH_INFO instead
    {
        GET_LENGTH_INFORMATION part_info = { 0 };

        status =
            ZwDeviceIoControlFile(FileHandle,
            NULL,
            NULL,
            NULL,
            IoStatus,
            IOCTL_DISK_GET_LENGTH_INFO,
            NULL,
            0,
            &part_info,
            sizeof(part_info));

        if (status == STATUS_PENDING)
        {
            ZwWaitForSingleObject(FileHandle, FALSE, NULL);
            status = IoStatus->Status;
        }

        if (NT_SUCCESS(status))
        {
            *DiskSize = part_info.Length;
            return status;
        }

        KdPrint(("PhDskMnt::IOCTL_DISK_GET_LENGTH_INFO not supported "
            "for target device. %#x\n", status));
    }

    // Retry with IOCTL_DISK_GET_PARTITION_INFO instead
    {
        PARTITION_INFORMATION part_info = { 0 };

        status =
            ZwDeviceIoControlFile(FileHandle,
            NULL,
            NULL,
            NULL,
            IoStatus,
            IOCTL_DISK_GET_PARTITION_INFO,
            NULL,
            0,
            &part_info,
            sizeof(part_info));

        if (status == STATUS_PENDING)
        {
            ZwWaitForSingleObject(FileHandle, FALSE, NULL);
            status = IoStatus->Status;
        }

        if (NT_SUCCESS(status))
        {
            *DiskSize = part_info.PartitionLength;
            return status;
        }

        KdPrint(("PhDskMnt::IOCTL_DISK_GET_PARTITION_INFO not supported "
            "for target device. %#x\n", status));
    }

    return status;
}
Beispiel #27
0
BOOLEAN
getSizeModified(
_In_ PFLT_INSTANCE instance,
_In_ PUNICODE_STRING fileName,
_Inout_ LONGLONG *size,
_Inout_ LONGLONG *modified
)
{
	NTSTATUS status;
	HANDLE FileHandle = NULL;
	OBJECT_ATTRIBUTES objectAttributes;
	IO_STATUS_BLOCK ioStatus;
	FILE_BASIC_INFORMATION basicFileInfo;
	FILE_STANDARD_INFORMATION standardFileInfo;

	InitializeObjectAttributes(&objectAttributes,
		fileName,
		OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
		NULL,
		NULL);

	status = FltCreateFile(
		ClaimsmanData.Filter,
		instance,
		&FileHandle,
		FILE_READ_DATA | FILE_READ_ATTRIBUTES,
		&objectAttributes,
		&ioStatus,
		NULL,
		FILE_ATTRIBUTE_NORMAL,
		FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE,
		FILE_OPEN,
		FILE_SYNCHRONOUS_IO_NONALERT,
		NULL,
		0,
		IO_NO_PARAMETER_CHECKING
		);
	if (!NT_SUCCESS(status)) {
		return FALSE;
	}

	status = ZwQueryInformationFile(FileHandle,
		&ioStatus,
		&basicFileInfo,
		sizeof(FILE_BASIC_INFORMATION),
		FileBasicInformation);

	if (!NT_SUCCESS(status)) {
		ZwClose(FileHandle);
		return FALSE;
	}

		status = ZwQueryInformationFile(FileHandle,
		&ioStatus,
		&standardFileInfo,
		sizeof(FILE_STANDARD_INFORMATION),
		FileStandardInformation);
		
	if (!NT_SUCCESS(status)) {
		ZwClose(FileHandle);
		return FALSE;
	}


	*modified = (basicFileInfo.ChangeTime.QuadPart - DIFF_TO_UNIX_EPOCH) / 10000;
	*size = standardFileInfo.EndOfFile.QuadPart;

	ZwClose(FileHandle);
	return TRUE;
}
Beispiel #28
0
NTSTATUS
GetNextReparseVolumePath(
    IN  HANDLE          Handle,
    OUT PUNICODE_STRING Path
    )

/*++

Routine Description:

    This routine queries the reparse index for the next volume mount point.

Arguments:

    Handle  - Supplies the handle.

    Path    - Returns the path.


Return Value:

    NTSTATUS

--*/

{
    NTSTATUS                        status;
    IO_STATUS_BLOCK                 ioStatus;
    FILE_REPARSE_POINT_INFORMATION  reparseInfo;
    UNICODE_STRING                  fileId;
    OBJECT_ATTRIBUTES               oa;
    HANDLE                          h;
    PREPARSE_DATA_BUFFER            reparse;
    UNICODE_STRING                  volumeName;
    ULONG                           nameInfoSize;
    PFILE_NAME_INFORMATION          nameInfo;

    for (;;) {

        status = ZwQueryDirectoryFile(Handle, NULL, NULL, NULL, &ioStatus,
                                      &reparseInfo, sizeof(reparseInfo),
                                      FileReparsePointInformation, TRUE, NULL,
                                      FALSE);
        if (!NT_SUCCESS(status)) {
            return status;
        }

        if (reparseInfo.Tag != IO_REPARSE_TAG_MOUNT_POINT) {
            continue;
        }

        fileId.Length = sizeof(reparseInfo.FileReference);
        fileId.MaximumLength = fileId.Length;
        fileId.Buffer = (PWSTR) &reparseInfo.FileReference;

        InitializeObjectAttributes(&oa, &fileId, 0, Handle, NULL);

        status = ZwOpenFile(&h, SYNCHRONIZE | FILE_GENERIC_READ, &oa,
                            &ioStatus, FILE_SHARE_READ | FILE_SHARE_WRITE,
                            FILE_OPEN_BY_FILE_ID | FILE_OPEN_REPARSE_POINT |
                            FILE_SYNCHRONOUS_IO_ALERT);
        if (!NT_SUCCESS(status)) {
            continue;
        }

        reparse = ExAllocatePool(PagedPool, MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
        if (!reparse) {
            ZwClose(h);
            return STATUS_INSUFFICIENT_RESOURCES;
        }

        status = ZwFsControlFile(h, NULL, NULL, NULL, &ioStatus,
                                 FSCTL_GET_REPARSE_POINT, NULL, 0, reparse,
                                 MAXIMUM_REPARSE_DATA_BUFFER_SIZE);
        if (!NT_SUCCESS(status)) {
            ExFreePool(reparse);
            ZwClose(h);
            continue;
        }

        volumeName.Length = reparse->MountPointReparseBuffer.SubstituteNameLength -
                            sizeof(WCHAR);
        volumeName.MaximumLength = volumeName.Length + sizeof(WCHAR);
        volumeName.Buffer = (PWCHAR)
                            ((PCHAR) reparse->MountPointReparseBuffer.PathBuffer +
                            reparse->MountPointReparseBuffer.SubstituteNameOffset);
        volumeName.Buffer[volumeName.Length/sizeof(WCHAR)] = 0;

        if (!IsVolumeName(&volumeName)) {
            ExFreePool(reparse);
            ZwClose(h);
            continue;
        }

        ExFreePool(reparse);

        nameInfoSize = 1024;
        nameInfo = ExAllocatePool(PagedPool, nameInfoSize);
        if (!nameInfo) {
            ZwClose(h);
            continue;
        }

        status = ZwQueryInformationFile(h, &ioStatus, nameInfo, nameInfoSize,
                                        FileNameInformation);
        ZwClose(h);
        if (!NT_SUCCESS(status)) {
            continue;
        }

        Path->Length = (USHORT) nameInfo->FileNameLength;
        Path->MaximumLength = Path->Length + sizeof(WCHAR);
        Path->Buffer = ExAllocatePool(PagedPool, Path->MaximumLength);
        if (!Path->Buffer) {
            ExFreePool(nameInfo);
            continue;
        }

        RtlCopyMemory(Path->Buffer, nameInfo->FileName, Path->Length);
        Path->Buffer[Path->Length/sizeof(WCHAR)] = 0;

        ExFreePool(nameInfo);
        break;
    }

    return status;
}
Beispiel #29
0
BOOLEAN
Primary_PassThrough(
	IN PLFS_DEVICE_EXTENSION	LfsDeviceExt,
	IN  PIRP					Irp,
	OUT PNTSTATUS				NtStatus
	)
{
	PIO_STACK_LOCATION  irpSp = IoGetCurrentIrpStackLocation(Irp);
	PFILE_OBJECT		fileObject;
	KIRQL		oldIrql;
	//	Do not allow exclusive access to the volume when connected to secondaries.

	if(irpSp->MajorFunction == IRP_MJ_FILE_SYSTEM_CONTROL 
		&& (irpSp->MinorFunction == IRP_MN_USER_FS_REQUEST || irpSp->MinorFunction == IRP_MN_KERNEL_CALL)) 
	{
		struct FileSystemControl	*fileSystemControl =(struct FileSystemControl *)&(irpSp->Parameters.FileSystemControl);

		fileObject = irpSp->FileObject;

		//
		//	Do not allow exclusive access to the volume and dismount volume to protect format
		//	We allow exclusive access if secondaries are connected locally.
		//

		if(
			(fileSystemControl->FsControlCode == FSCTL_LOCK_VOLUME				// 6
				|| fileSystemControl->FsControlCode == FSCTL_DISMOUNT_VOLUME)	// 8
			&& NetdiskManager_ThisVolumeHasSecondary(GlobalLfs.NetdiskManager, LfsDeviceExt->EnabledNetdisk, LfsDeviceExt, FALSE)
			)
		{
			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
						("Primary_PassThrough, IRP_MJ_FILE_SYSTEM_CONTROL: Trying to acquire the volume exclusively. \n"));


			ASSERT(fileObject 
					&& fileObject->FileName.Length == 0 
					&& fileObject->RelatedFileObject == NULL); 

			*NtStatus = Irp->IoStatus.Status = STATUS_ACCESS_DENIED;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_DISK_INCREMENT);

			return TRUE;


		//
		//	Do not support encryption.
		//

		} else if(fileSystemControl->FsControlCode == FSCTL_SET_ENCRYPTION) {

			SPY_LOG_PRINT( LFS_DEBUG_PRIMARY_INFO,
				("Primary_PassThrough, IRP_MJ_FILE_SYSTEM_CONTROL: Setting encryption denied.\n"));

			*NtStatus = Irp->IoStatus.Status = STATUS_NOT_SUPPORTED;
			Irp->IoStatus.Information = 0;
			IoCompleteRequest(Irp, IO_DISK_INCREMENT);

			return TRUE;
		}
	}

    // Need to test much whether this is okay..
	if (irpSp->MajorFunction == IRP_MJ_PNP && 
		(irpSp->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE || irpSp->MinorFunction == IRP_MN_REMOVE_DEVICE)) {
		PNETDISK_PARTITION Partition;
		Partition = LookUpNetdiskPartition(LfsDeviceExt->EnabledNetdisk, NULL, 0, LfsDeviceExt, NULL);
		if (Partition) {

			SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR,	("%s: Releasing Unplugging lock\n", 
				(irpSp->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE)?"CANCEL_REMOVE_DEVICE":"REMOVE_DEVICE"));
			InterlockedDecrement(&LfsDeviceExt->EnabledNetdisk->UnplugInProgressCount);
			NetdiskPartition_Dereference(Partition);		// by LookUpNetdiskPartition			
		} else {
			ASSERT(0);
			SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR,	("%s: Failed to find matching parition. Release unplugging lock anyway\n", 
				(irpSp->MinorFunction == IRP_MN_CANCEL_REMOVE_DEVICE)?"CANCEL_REMOVE_DEVICE":"REMOVE_DEVICE"));
			InterlockedDecrement(&LfsDeviceExt->EnabledNetdisk->UnplugInProgressCount);
		}
	}

	//
	// Close files opened by secondary if unmount of primary host is requested .
	// This helps primary can unmount while secondary has mounted.
	//
	if (irpSp->MajorFunction == IRP_MJ_PNP && irpSp->MinorFunction == IRP_MN_QUERY_REMOVE_DEVICE) {
		int i;
		PLIST_ENTRY	primarySessionListEntry;
		PLIST_ENTRY PrimarySessionList;
		POPEN_FILE	openFile;
	    PLIST_ENTRY	OpenFileListEntry;
	    NTSTATUS   closeStatus;
#if DBG
		int j;
		CHAR NameBuf[512] = {0};
#endif		
		PPRIMARY_SESSION primarySession;

		PNETDISK_PARTITION Partition;

		Partition = LookUpNetdiskPartition(LfsDeviceExt->EnabledNetdisk, NULL, 0, LfsDeviceExt, NULL);
		if (Partition) {
			SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR,	("QUERY_REMOVE: Locking disks for removal\n"));
			InterlockedIncrement(&LfsDeviceExt->EnabledNetdisk->UnplugInProgressCount);
			// wait until DispatchInProgressCount becomes zero
			KeAcquireSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, &oldIrql);
			while(LfsDeviceExt->EnabledNetdisk->DispatchInProgressCount>0) {
				LARGE_INTEGER Timeout;
				SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR,	("QUERY_REMOVE: %d IO is in progress by secondary\n", LfsDeviceExt->EnabledNetdisk->DispatchInProgressCount));
				Timeout.QuadPart = - HZ/10; // 100ms
				KeReleaseSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, oldIrql);
				KeDelayExecutionThread(KernelMode, FALSE, &Timeout);
				KeAcquireSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, &oldIrql);
			}
			KeReleaseSpinLock(&LfsDeviceExt->EnabledNetdisk->SpinLock, oldIrql);

			NetdiskPartition_Dereference(Partition);		// by LookUpNetdiskPartition
			
		} else {
			SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR,	("QUERY_REMOVE: Failed to find matching parition\n"));
		}

		for(i=0;i<MAX_SOCKETLPX_INTERFACE;i++) {
			PrimarySessionList = &GlobalLfs.Primary->PrimarySessionQueue[i];

			for (primarySessionListEntry = PrimarySessionList->Flink;
				 primarySessionListEntry != PrimarySessionList;
				 primarySessionListEntry = primarySessionListEntry->Flink)
			{		
				primarySession = CONTAINING_RECORD (primarySessionListEntry, PRIMARY_SESSION, ListEntry);
				if (primarySession->NetdiskPartition == NULL || 
					primarySession->NetdiskPartition->EnabledNetdisk == NULL) {
					SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO,
						("Primary is closed: Session=%p\n",
						primarySession
					));
					continue;
				}
				
				//
				// Is there any way to check to get proper netdisk??
				//
				if (primarySession->NetdiskPartition->EnabledNetdisk == LfsDeviceExt->EnabledNetdisk) {
				    for (OpenFileListEntry = primarySession->OpenedFileQueue.Flink;
				         OpenFileListEntry != &primarySession->OpenedFileQueue;
				         OpenFileListEntry = OpenFileListEntry->Flink) 
					{
						openFile = CONTAINING_RECORD (OpenFileListEntry, OPEN_FILE, ListEntry);

						// Close open files opened by secondary.
						if (openFile->AlreadyClosed == FALSE) {
							// Store file offset before close.
							
							if (openFile->CreateOptions &(FILE_SYNCHRONOUS_IO_ALERT |FILE_SYNCHRONOUS_IO_NONALERT)) {
								NTSTATUS QueryStatus;
								IO_STATUS_BLOCK IoStatus;
								FILE_POSITION_INFORMATION FileInfo;
								
								// File position is meaningful only in this open mode.
								QueryStatus = ZwQueryInformationFile(
									openFile->FileHandle,
									&IoStatus, 
									(PVOID)&FileInfo,
									sizeof(FileInfo),
									FilePositionInformation
								);
								if (NT_SUCCESS(QueryStatus)) {
									SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO,
												("Closing secondary files: Stroring offset %x\n", FileInfo.CurrentByteOffset));
									openFile->CurrentByteOffset = FileInfo.CurrentByteOffset;
								} else {
									SPY_LOG_PRINT( LFS_DEBUG_LFS_ERROR,
												("Closing secondary files: Failed to get current file offset\n"));
									openFile->CurrentByteOffset.HighPart = 0;
									openFile->CurrentByteOffset.LowPart = 0;									
								}
							}

							closeStatus = ZwClose(openFile->FileHandle);
							ObDereferenceObject(openFile->FileObject);
							ASSERT(openFile->EventHandle !=NULL);
							ZwClose(openFile->EventHandle);
							openFile->EventHandle = NULL;
							openFile->AlreadyClosed = TRUE;
						}
#if DBG						
						// Print of unicode is available only PASSIVE_LEVEL. 
						// So print in ASCII assuming file name is always ascii range.
						for(j=0;openFile->FullFileNameBuffer[j]!=0 && j<sizeof(NameBuf)-1;j++) {
							NameBuf[j]= (CHAR)openFile->FullFileNameBuffer[j];
						}
						NameBuf[j] = 0;
						SPY_LOG_PRINT( LFS_DEBUG_LFS_INFO,
									("Closing secondary files: Session=%p, FileId=%x, FileName=%s\n",
									primarySession,
									openFile->OpenFileId,
									NameBuf
									));
#endif
					}
				}
			}
		}
	}

	 return FALSE;
}
Beispiel #30
0
/* Attempt to impersonate a client and open a file for the filedisk. */
static VOID STDCALL WvFilediskOpenInThread_(IN OUT WVL_SP_THREAD_ITEM item) {
    WV_SP_FILEDISK_OPENER_ opener = CONTAINING_RECORD(
        item,
        WV_S_FILEDISK_OPENER_,
        item[0]
      );
    OBJECT_ATTRIBUTES obj_attrs;
    HANDLE file = NULL;
    IO_STATUS_BLOCK io_status;
    FILE_STANDARD_INFORMATION file_info;

    /* Impersonate the user creating the filedisk. */
    opener->status = WvFilediskImpersonate(opener->filedisk->impersonation);
    if (!NT_SUCCESS(opener->status)) {
        DBG("Couldn't impersonate!\n");
        goto err_impersonate;
      }

    /* Open the file. */
    InitializeObjectAttributes(
        &obj_attrs,
        opener->file_path,
        OBJ_KERNEL_HANDLE | OBJ_CASE_INSENSITIVE,
        NULL,
        NULL
      );
    /* Open the file.  The handle is closed when the thread finishes. */
    opener->status = ZwCreateFile(
        &file,
        GENERIC_READ | GENERIC_WRITE,
        &obj_attrs,
        &io_status,
        NULL,
        FILE_ATTRIBUTE_NORMAL,
        FILE_SHARE_READ | FILE_SHARE_DELETE | FILE_SHARE_WRITE,
        FILE_OPEN,
        FILE_NON_DIRECTORY_FILE |
          FILE_RANDOM_ACCESS |
          FILE_NO_INTERMEDIATE_BUFFERING |
          FILE_SYNCHRONOUS_IO_NONALERT,
        NULL,
        0
      );
    if (!NT_SUCCESS(opener->status)) {
        DBG("Couldn't open file!\n");
        goto err_open;
      }

    /* Determine the disk's size. */
    opener->status = ZwQueryInformationFile(
        file,
        &io_status,
        &file_info,
        sizeof file_info,
        FileStandardInformation
      );
    if (!NT_SUCCESS(opener->status)) {
        DBG("Couldn't query file size!\n");
        goto err_query_info;
      }
    opener->filedisk->disk->LBADiskSize =
      file_info.EndOfFile.QuadPart / opener->filedisk->disk->SectorSize;

    /*
     * A really stupid "hash".  RtlHashUnicodeString() would have been
     * good, but is only available >= Windows XP.
     */
    opener->filedisk->hash = (UINT32) opener->filedisk->disk->LBADiskSize;
    {   PWCHAR path_iterator = opener->file_path->Buffer;
    
        while (*path_iterator)
          opener->filedisk->hash += *path_iterator++;
      }

    /* Opened. */
    opener->filedisk->file = file;
    goto out;

    err_query_info:

    ZwClose(file);
    err_open:

    out:

    WvFilediskStopImpersonating();
    err_impersonate:

    KeSetEvent(opener->completion, 0, FALSE);
    return;
  }