External/WinRing0/OpenLibSys.c
author moel.mich
Sun, 27 May 2012 16:50:01 +0000
changeset 347 d043dac9f34e
permissions -rw-r--r--
Added the source code of the WinRing0 device driver.
     1 //-----------------------------------------------------------------------------
     2 //     Author : hiyohiyo
     3 //       Mail : hiyohiyo@crystalmark.info
     4 //        Web : http://openlibsys.org/
     5 //    License : The modified BSD license
     6 //
     7 //                     Copyright 2007-2008 OpenLibSys.org. All rights reserved.
     8 //-----------------------------------------------------------------------------
     9 
    10 #include <ntddk.h>
    11 #include <stddef.h>
    12 #include "OpenLibSys.h"
    13 
    14 //-----------------------------------------------------------------------------
    15 //
    16 // Global
    17 //
    18 //-----------------------------------------------------------------------------
    19 
    20 static ULONG refCount;
    21 
    22 //-----------------------------------------------------------------------------
    23 //
    24 // Classic NT driver
    25 // DriverEntry / OlsDispatch / Unload
    26 //
    27 //-----------------------------------------------------------------------------
    28 
    29 NTSTATUS
    30 DriverEntry(
    31 	IN PDRIVER_OBJECT  DriverObject,
    32 	IN PUNICODE_STRING RegistryPath
    33 	)
    34 
    35 /*
    36 
    37 Return Value:
    38 
    39 	STATUS_SUCCESS if the driver initialized correctly, otherwise an erroror
    40 	indicating the reason for failure.
    41 */
    42 
    43 {
    44 	NTSTATUS		status;
    45 	UNICODE_STRING  ntDeviceName;
    46 	UNICODE_STRING  win32DeviceName;
    47 	PDEVICE_OBJECT  deviceObject = NULL;
    48 
    49 	RtlInitUnicodeString(&ntDeviceName, NT_DEVICE_NAME);
    50 
    51 	status = IoCreateDevice(
    52 		DriverObject,					// Our Driver Object
    53 		0,								// We don't use a device extension
    54 		&ntDeviceName,					// Device name 
    55 		OLS_TYPE,						// Device type
    56 		FILE_DEVICE_SECURE_OPEN,		// Device characteristics
    57 		FALSE,							// Not an exclusive device
    58 		&deviceObject );				// Returned ptr to Device Object
    59 
    60 	if(!NT_SUCCESS(status))
    61 	{
    62 		refCount = (ULONG)-1;
    63 		return status;
    64 	}
    65 	else
    66 	{
    67 		refCount = 0;
    68 	}
    69 
    70 	// Initialize the driver object with this driver's entry points.
    71 	DriverObject->MajorFunction[IRP_MJ_CREATE] = OlsDispatch;
    72 	DriverObject->MajorFunction[IRP_MJ_CLOSE] = OlsDispatch;
    73 	DriverObject->MajorFunction[IRP_MJ_DEVICE_CONTROL] = OlsDispatch;
    74 	DriverObject->DriverUnload = Unload;
    75 
    76 	// Initialize a Unicode String containing the Win32 name for our device.
    77 	RtlInitUnicodeString(&win32DeviceName, DOS_DEVICE_NAME);
    78 
    79 	// Create a symbolic link between our device name  and the Win32 name
    80 	status = IoCreateSymbolicLink(&win32DeviceName, &ntDeviceName);
    81 
    82 	if (!NT_SUCCESS(status))
    83 	{
    84 		// Delete everything that this routine has allocated.
    85 		IoDeleteDevice( deviceObject );
    86 	}
    87 
    88 	return status;
    89 }
    90 
    91 NTSTATUS
    92 OlsDispatch(
    93 	IN	PDEVICE_OBJECT pDO,
    94 	IN	PIRP pIrp
    95 	)
    96 
    97 /*++
    98 
    99 Routine Description:
   100 	This routine is the dispatch handler for the driver.  It is responsible
   101 	for processing the IRPs.
   102 
   103 Arguments:
   104 	
   105 	pDO - Pointer to device object.
   106 
   107 	pIrp - Pointer to the current IRP.
   108 
   109 Return Value:
   110 
   111 	STATUS_SUCCESS if the IRP was processed successfully, otherwise an erroror
   112 	indicating the reason for failure.
   113 
   114 --*/
   115 
   116 {
   117 	PIO_STACK_LOCATION pIrpStack;
   118 	NTSTATUS status;
   119 	int index;
   120 
   121 	//  Initialize the irp info field.
   122 	//	  This is used to return the number of bytes transfered.
   123 	pIrp->IoStatus.Information = 0;
   124 	pIrpStack = IoGetCurrentIrpStackLocation(pIrp);
   125 
   126 	//  Set default return status
   127 	status = STATUS_NOT_IMPLEMENTED;
   128 
   129 	// Dispatch based on major fcn code.
   130 	switch(pIrpStack->MajorFunction)
   131 	{
   132 		case IRP_MJ_CREATE:
   133 			if(refCount != (ULONG)-1){refCount++;}
   134 			status = STATUS_SUCCESS;
   135 			break;
   136 		case IRP_MJ_CLOSE:
   137 			if(refCount != (ULONG)-1){refCount--;}
   138 			status = STATUS_SUCCESS;
   139 			break;
   140 
   141 		case IRP_MJ_DEVICE_CONTROL:
   142 			//  Dispatch on IOCTL
   143 			switch(pIrpStack->Parameters.DeviceIoControl.IoControlCode)
   144 			{
   145 			case IOCTL_OLS_GET_DRIVER_VERSION:
   146 				*(PULONG)pIrp->AssociatedIrp.SystemBuffer = OLS_DRIVER_VERSION;
   147 				pIrp->IoStatus.Information = 4;
   148 				status = STATUS_SUCCESS;
   149 				break;
   150 
   151 			case IOCTL_OLS_GET_REFCOUNT:
   152 				*(PULONG)pIrp->AssociatedIrp.SystemBuffer = refCount;
   153 				pIrp->IoStatus.Information = sizeof(refCount);
   154 				status = STATUS_SUCCESS;
   155 				break;
   156 
   157 			case IOCTL_OLS_READ_MSR:
   158 				status = ReadMsr(
   159 					pIrp->AssociatedIrp.SystemBuffer,
   160 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   161 					pIrp->AssociatedIrp.SystemBuffer,
   162 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   163 					(ULONG*)&pIrp->IoStatus.Information
   164 					);
   165 				break;
   166 			case IOCTL_OLS_WRITE_MSR:
   167 				status = WriteMsr(
   168 					pIrp->AssociatedIrp.SystemBuffer,
   169 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   170 					pIrp->AssociatedIrp.SystemBuffer,
   171 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   172 					(ULONG*)&pIrp->IoStatus.Information
   173 					);
   174 				break;
   175 			case IOCTL_OLS_READ_PMC:
   176 				status = ReadPmc(
   177 					pIrp->AssociatedIrp.SystemBuffer,
   178 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   179 					pIrp->AssociatedIrp.SystemBuffer,
   180 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   181 					(ULONG*)&pIrp->IoStatus.Information
   182 					);
   183 				break;
   184 			case IOCTL_OLS_HALT:
   185 				__halt();
   186 				status = STATUS_SUCCESS;
   187 				break;
   188 
   189 			case IOCTL_OLS_READ_IO_PORT:
   190 			case IOCTL_OLS_READ_IO_PORT_BYTE:
   191 			case IOCTL_OLS_READ_IO_PORT_WORD:
   192 			case IOCTL_OLS_READ_IO_PORT_DWORD:
   193 				status = ReadIoPort(
   194 					pIrpStack->Parameters.DeviceIoControl.IoControlCode,
   195 					pIrp->AssociatedIrp.SystemBuffer,
   196 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   197 					pIrp->AssociatedIrp.SystemBuffer,
   198 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   199 					(ULONG*)&pIrp->IoStatus.Information
   200 					);
   201 				break;
   202 			case IOCTL_OLS_WRITE_IO_PORT:
   203 			case IOCTL_OLS_WRITE_IO_PORT_BYTE:
   204 			case IOCTL_OLS_WRITE_IO_PORT_WORD:
   205 			case IOCTL_OLS_WRITE_IO_PORT_DWORD:
   206 				status = WriteIoPort(
   207 					pIrpStack->Parameters.DeviceIoControl.IoControlCode,
   208 					pIrp->AssociatedIrp.SystemBuffer,
   209 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   210 					pIrp->AssociatedIrp.SystemBuffer,
   211 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   212 					(ULONG*)&pIrp->IoStatus.Information
   213 					);
   214 				break;
   215 
   216 			case IOCTL_OLS_READ_PCI_CONFIG:
   217 				status = ReadPciConfig(
   218 					pIrp->AssociatedIrp.SystemBuffer,
   219 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   220 					pIrp->AssociatedIrp.SystemBuffer,
   221 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   222 					(ULONG*)&pIrp->IoStatus.Information
   223 					);
   224 				break;
   225 			case IOCTL_OLS_WRITE_PCI_CONFIG:
   226 				status = WritePciConfig(
   227 					pIrp->AssociatedIrp.SystemBuffer,
   228 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   229 					pIrp->AssociatedIrp.SystemBuffer,
   230 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   231 					(ULONG*)&pIrp->IoStatus.Information
   232 					);
   233 				break;
   234 
   235 			case IOCTL_OLS_READ_MEMORY:
   236 				status = ReadMemory(
   237 					pIrp->AssociatedIrp.SystemBuffer,
   238 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   239 					pIrp->AssociatedIrp.SystemBuffer,
   240 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   241 					(ULONG*)&pIrp->IoStatus.Information
   242 					);
   243 				break;
   244 			case IOCTL_OLS_WRITE_MEMORY:
   245 				status = WriteMemory(
   246 					pIrp->AssociatedIrp.SystemBuffer,
   247 					pIrpStack->Parameters.DeviceIoControl.InputBufferLength,
   248 					pIrp->AssociatedIrp.SystemBuffer,
   249 					pIrpStack->Parameters.DeviceIoControl.OutputBufferLength,
   250 					(ULONG*)&pIrp->IoStatus.Information
   251 					);
   252 				break;
   253 
   254 
   255 			}
   256 			break;
   257 	}
   258 
   259 	// We're done with I/O request.  Record the status of the I/O action.
   260 	pIrp->IoStatus.Status = status;
   261 
   262 	// Don't boost priority when returning since this took little time.
   263 	IoCompleteRequest(pIrp, IO_NO_INCREMENT);
   264 
   265 	return status;
   266 }
   267 
   268 VOID
   269 Unload(
   270 	PDRIVER_OBJECT DriverObject
   271 	)
   272 /*++
   273 
   274 Routine Description:
   275 
   276 	This routine is called by the I/O system to unload the driver.
   277 
   278 	Any resources previously allocated must be freed.
   279 
   280 Arguments:
   281 
   282 	DriverObject - a pointer to the object that represents our driver.
   283 
   284 Return Value:
   285 
   286 	None
   287 --*/
   288 
   289 {
   290 	PDEVICE_OBJECT deviceObject = DriverObject->DeviceObject;
   291 	UNICODE_STRING win32NameString;
   292 
   293 	PAGED_CODE();
   294 
   295 	// Create counted string version of our Win32 device name.
   296 	RtlInitUnicodeString(&win32NameString, DOS_DEVICE_NAME);
   297 
   298 	// Delete the link from our device name to a name in the Win32 namespace.
   299 	IoDeleteSymbolicLink(&win32NameString);
   300 
   301 	if(deviceObject != NULL)
   302 	{
   303 		IoDeleteDevice(deviceObject);
   304 	}
   305 }
   306 
   307 //-----------------------------------------------------------------------------
   308 //
   309 // CPU
   310 //
   311 //-----------------------------------------------------------------------------
   312 
   313 NTSTATUS
   314 ReadMsr(	void	*lpInBuffer, 
   315 			ULONG	nInBufferSize, 
   316 			void	*lpOutBuffer, 
   317 			ULONG	nOutBufferSize, 
   318 			ULONG	*lpBytesReturned)
   319 {
   320 	__try
   321 	{
   322 		ULONGLONG data = __readmsr(*(ULONG*)lpInBuffer);
   323 		memcpy((PULONG)lpOutBuffer, &data, 8);
   324 		*lpBytesReturned = 8;
   325 		return STATUS_SUCCESS;
   326 	}
   327 	__except(EXCEPTION_EXECUTE_HANDLER)
   328 	{
   329 		*lpBytesReturned = 0;
   330 		return STATUS_UNSUCCESSFUL;
   331 	}
   332 }
   333 
   334 NTSTATUS
   335 WriteMsr(	void	*lpInBuffer, 
   336 			ULONG	nInBufferSize, 
   337 			void	*lpOutBuffer, 
   338 			ULONG	nOutBufferSize, 
   339 			ULONG	*lpBytesReturned)
   340 {
   341 	__try
   342 	{
   343 		OLS_WRITE_MSR_INPUT* param;
   344 		param = (OLS_WRITE_MSR_INPUT*)lpInBuffer;
   345 
   346 		__writemsr(param->Register, param->Value.QuadPart);
   347 		*lpBytesReturned = 0;
   348 		return STATUS_SUCCESS;
   349 	}
   350 	__except(EXCEPTION_EXECUTE_HANDLER)
   351 	{
   352 		*lpBytesReturned = 0;
   353 		return STATUS_UNSUCCESSFUL;
   354 	}
   355 }
   356 
   357 NTSTATUS
   358 ReadPmc(	void	*lpInBuffer, 
   359 			ULONG	nInBufferSize, 
   360 			void	*lpOutBuffer, 
   361 			ULONG	nOutBufferSize, 
   362 			ULONG	*lpBytesReturned)
   363 {
   364 	__try
   365 	{
   366 		ULONGLONG data = __readpmc(*(ULONG*)lpInBuffer);
   367 		memcpy((PULONG)lpOutBuffer, &data, 8);
   368 		*lpBytesReturned = 8;
   369 		return STATUS_SUCCESS;
   370 	}
   371 	__except(EXCEPTION_EXECUTE_HANDLER)
   372 	{
   373 		*lpBytesReturned = 0;
   374 		return STATUS_UNSUCCESSFUL;
   375 	}
   376 }
   377 
   378 //-----------------------------------------------------------------------------
   379 //
   380 // IO Port
   381 //
   382 //-----------------------------------------------------------------------------
   383 
   384 NTSTATUS
   385 ReadIoPort( ULONG	ioControlCode,
   386 			void	*lpInBuffer, 
   387 			ULONG	nInBufferSize, 
   388 			void	*lpOutBuffer, 
   389 			ULONG	nOutBufferSize, 
   390 			ULONG	*lpBytesReturned)
   391 {
   392 	ULONG nPort = *(ULONG*)lpInBuffer;
   393 
   394 	switch(ioControlCode)
   395 	{
   396 		case IOCTL_OLS_READ_IO_PORT_BYTE:
   397 			*(PUCHAR)lpOutBuffer = READ_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort);
   398 			break;
   399 		case IOCTL_OLS_READ_IO_PORT_WORD:
   400 			*(PUSHORT)lpOutBuffer = READ_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort);
   401 			break;
   402 		case IOCTL_OLS_READ_IO_PORT_DWORD:
   403 			*(PULONG)lpOutBuffer = READ_PORT_ULONG((PULONG)(ULONG_PTR)nPort);
   404 			break;
   405 		default:
   406 			*lpBytesReturned = 0;
   407 			return STATUS_INVALID_PARAMETER;
   408 			break;
   409 	}
   410 	
   411 	*lpBytesReturned = nInBufferSize;
   412 	return STATUS_SUCCESS;
   413 }
   414 
   415 NTSTATUS
   416 WriteIoPort(ULONG	ioControlCode,
   417 			void	*lpInBuffer, 
   418 			ULONG	nInBufferSize, 
   419 			void	*lpOutBuffer, 
   420 			ULONG	nOutBufferSize, 
   421 			ULONG	*lpBytesReturned)
   422 {
   423 	ULONG nPort;
   424 	OLS_WRITE_IO_PORT_INPUT* param;
   425 	
   426 	param = (OLS_WRITE_IO_PORT_INPUT*)lpInBuffer;
   427 	nPort = param->PortNumber;
   428 
   429 	switch(ioControlCode)
   430 	{
   431 
   432 		case IOCTL_OLS_WRITE_IO_PORT_BYTE:
   433 			WRITE_PORT_UCHAR((PUCHAR)(ULONG_PTR)nPort, param->CharData);
   434 			break;
   435 		case IOCTL_OLS_WRITE_IO_PORT_WORD:
   436 			WRITE_PORT_USHORT((PUSHORT)(ULONG_PTR)nPort, param->ShortData);
   437 			break;
   438 		case IOCTL_OLS_WRITE_IO_PORT_DWORD:
   439 			WRITE_PORT_ULONG((PULONG)(ULONG_PTR)nPort, param->LongData);
   440 			break;
   441 		default:
   442 			return STATUS_INVALID_PARAMETER;
   443 			break;
   444 	}
   445 
   446 	return STATUS_SUCCESS;
   447 }
   448 
   449 //-----------------------------------------------------------------------------
   450 //
   451 // PCI
   452 //
   453 //-----------------------------------------------------------------------------
   454 
   455 NTSTATUS
   456 ReadPciConfig(	void	*lpInBuffer, 
   457 				ULONG	nInBufferSize, 
   458 				void	*lpOutBuffer, 
   459 				ULONG	nOutBufferSize, 
   460 				ULONG	*lpBytesReturned)
   461 {
   462 	OLS_READ_PCI_CONFIG_INPUT *param;
   463 	NTSTATUS status;
   464 
   465 	if(nInBufferSize != sizeof(OLS_READ_PCI_CONFIG_INPUT))
   466 	{
   467 		return STATUS_INVALID_PARAMETER;
   468 	}
   469 	param = (OLS_READ_PCI_CONFIG_INPUT *)lpInBuffer;
   470 
   471 	status = pciConfigRead(param->PciAddress, param->PciOffset,
   472 						lpOutBuffer, nOutBufferSize);
   473 
   474 	if(status == STATUS_SUCCESS)
   475 	{
   476 		*lpBytesReturned = nOutBufferSize;
   477 	}
   478 	else
   479 	{
   480 		*lpBytesReturned = 0;
   481 	}
   482 
   483 	return status;
   484 }
   485 
   486 NTSTATUS
   487 WritePciConfig(	void *lpInBuffer, 
   488 				ULONG nInBufferSize, 
   489 				void *lpOutBuffer, 
   490 				ULONG nOutBufferSize, 
   491 				ULONG *lpBytesReturned)
   492 
   493 {
   494 	OLS_WRITE_PCI_CONFIG_INPUT *param;
   495 	ULONG writeSize;
   496 	NTSTATUS status;
   497 
   498 	if(nInBufferSize < offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data))
   499 	{
   500 		return STATUS_INVALID_PARAMETER;
   501 	}
   502 
   503 	param = (OLS_WRITE_PCI_CONFIG_INPUT *)lpInBuffer;
   504 	writeSize = nInBufferSize - offsetof(OLS_WRITE_PCI_CONFIG_INPUT, Data);
   505 	
   506 	*lpBytesReturned = 0;
   507 
   508 	return pciConfigWrite(param->PciAddress, param->PciOffset,
   509 							&param->Data, writeSize);
   510 
   511 }
   512 
   513 //-----------------------------------------------------------------------------
   514 //
   515 // Support Function
   516 //
   517 //-----------------------------------------------------------------------------
   518 
   519 NTSTATUS pciConfigRead(ULONG pciAddress, ULONG offset, void *data, int length)
   520 {
   521 	PCI_SLOT_NUMBER slot;
   522 	int error;
   523 	ULONG busNumber;
   524 
   525 	busNumber = PciGetBus(pciAddress);
   526 	slot.u.AsULONG = 0;
   527 	slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
   528 	slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
   529 	error =	HalGetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
   530 									data, offset, length);
   531 
   532 	if(error == 0)
   533 	{
   534 		return OLS_ERROR_PCI_BUS_NOT_EXIST;
   535 	}
   536 	else if(length != 2 && error == 2)
   537 	{
   538 		return OLS_ERROR_PCI_NO_DEVICE;
   539 	}
   540 	else if(length != error)
   541 	{
   542 		return OLS_ERROR_PCI_READ_CONFIG;
   543 	}
   544 
   545 	return STATUS_SUCCESS;
   546 }
   547 
   548 NTSTATUS pciConfigWrite(ULONG pciAddress, ULONG offset, void *data, int length)
   549 {
   550 	PCI_SLOT_NUMBER slot;
   551 	int error;
   552 	ULONG busNumber;
   553 
   554 	busNumber = PciGetBus(pciAddress);
   555 
   556 	slot.u.AsULONG = 0;
   557 	slot.u.bits.DeviceNumber = PciGetDev(pciAddress);
   558 	slot.u.bits.FunctionNumber = PciGetFunc(pciAddress);
   559 	error = HalSetBusDataByOffset(PCIConfiguration, busNumber, slot.u.AsULONG,
   560 									data, offset, length);
   561 
   562 	if(error != length)
   563 	{
   564 		return OLS_ERROR_PCI_WRITE_CONFIG;
   565 	}
   566 
   567 	return STATUS_SUCCESS;
   568 }
   569 
   570 
   571 //-----------------------------------------------------------------------------
   572 //
   573 // Physical Memory
   574 //
   575 //-----------------------------------------------------------------------------
   576 
   577 NTSTATUS
   578 ReadMemory(	void	*lpInBuffer, 
   579 			ULONG	nInBufferSize, 
   580 			void	*lpOutBuffer, 
   581 			ULONG	nOutBufferSize, 
   582 			ULONG	*lpBytesReturned)
   583 {
   584 	OLS_READ_MEMORY_INPUT *param;
   585 	ULONG	size;
   586 	PHYSICAL_ADDRESS address;
   587 	PVOID	maped;
   588 	BOOLEAN	error;
   589 
   590 	if(nInBufferSize != sizeof(OLS_READ_MEMORY_INPUT))
   591 	{
   592 		return STATUS_INVALID_PARAMETER;
   593 	}
   594 
   595 	param = (OLS_READ_MEMORY_INPUT *)lpInBuffer;
   596 	size = param->UnitSize * param->Count;
   597 
   598 	if(nOutBufferSize < size)
   599 	{
   600 		return STATUS_INVALID_PARAMETER;
   601 	}
   602 
   603 	address.QuadPart = param->Address.QuadPart;
   604 
   605 #ifndef _PHYSICAL_MEMORY_SUPPORT
   606 
   607 	if(0x000C0000 > address.QuadPart 
   608 	|| (address.QuadPart + size - 1) > 0x000FFFFF)
   609 	{
   610 		return STATUS_INVALID_PARAMETER;
   611 	}
   612 
   613 #endif
   614 
   615 	maped = MmMapIoSpace(address, size, FALSE);
   616 
   617 	error = FALSE;
   618 	switch(param->UnitSize){
   619 		case 1:
   620 			READ_REGISTER_BUFFER_UCHAR(maped, lpOutBuffer, param->Count);
   621 			break;
   622 		case 2:
   623 			READ_REGISTER_BUFFER_USHORT(maped, lpOutBuffer, param->Count);
   624 			break;
   625 		case 4:
   626 			READ_REGISTER_BUFFER_ULONG(maped, lpOutBuffer, param->Count);
   627 			break;
   628 		default:
   629 			error = TRUE;
   630 			break;
   631 	}
   632 
   633 	MmUnmapIoSpace(maped, size);
   634 
   635 	if(error)
   636 	{
   637 		return STATUS_INVALID_PARAMETER;
   638 	}
   639 
   640 	*lpBytesReturned = nOutBufferSize;
   641 
   642 	return STATUS_SUCCESS;
   643 }
   644 
   645 NTSTATUS
   646 WriteMemory(void	*lpInBuffer, 
   647 			ULONG	nInBufferSize, 
   648 			void	*lpOutBuffer, 
   649 			ULONG	nOutBufferSize, 
   650 			ULONG	*lpBytesReturned)
   651 {
   652 #ifdef _PHYSICAL_MEMORY_SUPPORT
   653 
   654 	OLS_WRITE_MEMORY_INPUT *param;
   655 	ULONG size;
   656 	PHYSICAL_ADDRESS address;
   657 	PVOID	maped;
   658 	BOOLEAN	error;
   659 
   660 	if(nInBufferSize < offsetof(OLS_WRITE_MEMORY_INPUT, Data))
   661 	{
   662 		return STATUS_INVALID_PARAMETER;
   663 	}
   664 
   665 	param = (OLS_WRITE_MEMORY_INPUT *)lpInBuffer;
   666 
   667 	size = param->UnitSize * param->Count;
   668 	if (nInBufferSize < size + offsetof(OLS_WRITE_MEMORY_INPUT, Data))
   669 	{
   670 		return STATUS_INVALID_PARAMETER;
   671 	}
   672 
   673 	address.QuadPart = param->Address.QuadPart;
   674 
   675 	maped = MmMapIoSpace(address, size, FALSE);
   676 
   677 	error = FALSE;
   678 	switch(param->UnitSize){
   679 		case 1:
   680 			WRITE_REGISTER_BUFFER_UCHAR(maped, 
   681 										(UCHAR*)&param->Data, param->Count);
   682 			break;
   683 		case 2:
   684 			WRITE_REGISTER_BUFFER_USHORT(maped,
   685 										(USHORT*)&param->Data, param->Count);
   686 			break;
   687 		case 4:
   688 			WRITE_REGISTER_BUFFER_ULONG(maped,
   689 										(ULONG*)&param->Data, param->Count);
   690 			break;
   691 		default:
   692 			error = TRUE;
   693 			break;
   694 	}
   695 
   696 	MmUnmapIoSpace(maped, size);
   697 
   698 	if(error)
   699 	{
   700 		return STATUS_INVALID_PARAMETER;
   701 	}
   702 
   703 	*lpBytesReturned = 0;
   704 
   705 	return STATUS_SUCCESS;
   706 
   707 #else
   708 
   709 	*lpBytesReturned = 0;
   710 	
   711 	return STATUS_INVALID_PARAMETER;
   712 
   713 #endif
   714 }