/* 
 *	Class:
 *
 *		WmiIoScheduler
 *
 *	Description:
 *
 *		Provides abstraction above heap allocation functions
 *
 *	Version:
 *
 *		Initial
 *
 *	Last Changed:
 *
 *		See Source Depot for change history
 *
 */

#include <precomp.h>
#include <windows.h>
#include <objbase.h>
#include <stdio.h>
#include <typeinfo.h>
#include <wbemcli.h>

#include <IoScheduler.h>

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode Win32ToApi ( DWORD a_Error ) 
{
	WmiStatusCode t_Status = e_StatusCode_Success ;
	switch ( a_Error )
	{
		case STATUS_NO_MEMORY:
		{
			t_Status = e_StatusCode_OutOfMemory ;
		}
		break ;

		default:
		{
			t_Status = e_StatusCode_Unknown ;
		}
		break ;
	}

	return t_Status ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode Win32ToApi () 
{
	WmiStatusCode t_Status = e_StatusCode_Success ;

	DWORD t_LastError = GetLastError () ;
	t_Status = Win32ToApi ( t_LastError ) ;

	return t_Status ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

HRESULT GetSecurityDescriptor ( SECURITY_DESCRIPTOR &a_SecurityDescriptor , DWORD a_Access ) 
{
	HRESULT t_Result = S_OK ;

	BOOL t_BoolResult = InitializeSecurityDescriptor ( & a_SecurityDescriptor , SECURITY_DESCRIPTOR_REVISION ) ;
	if ( t_BoolResult )
	{
		SID_IDENTIFIER_AUTHORITY t_NtAuthoritySid = SECURITY_NT_AUTHORITY ;

		PSID t_Administrator_Sid = NULL ;
		ACCESS_ALLOWED_ACE *t_Administrator_ACE = NULL ;
		WORD t_Administrator_ACESize = 0 ;

		BOOL t_BoolResult = AllocateAndInitializeSid (

			& t_NtAuthoritySid ,
			2 ,
			SECURITY_BUILTIN_DOMAIN_RID,
			DOMAIN_ALIAS_RID_ADMINS,
			0,
			0,
			0,
			0,
			0,
			0,
			& t_Administrator_Sid
		);

		if ( t_BoolResult )
		{
			DWORD t_SidLength = ::GetLengthSid ( t_Administrator_Sid );
			t_Administrator_ACESize = sizeof(ACCESS_ALLOWED_ACE) + (WORD) ( t_SidLength - sizeof(DWORD) ) ;
			t_Administrator_ACE = (ACCESS_ALLOWED_ACE*) new BYTE [ t_Administrator_ACESize ] ;
			if ( t_Administrator_ACE )
			{
				CopySid ( t_SidLength, (PSID) & t_Administrator_ACE->SidStart, t_Administrator_Sid ) ;
				t_Administrator_ACE->Mask = 0x1F01FF;
				t_Administrator_ACE->Header.AceType = 0 ;
				t_Administrator_ACE->Header.AceFlags = 3 ;
				t_Administrator_ACE->Header.AceSize = t_Administrator_ACESize ;
			}
			else
			{
				t_Result = WBEM_E_OUT_OF_MEMORY ;
			}
		}
		else
		{
			DWORD t_LastError = ::GetLastError();

			t_Result = WBEM_E_OUT_OF_MEMORY ;
		}

		PSID t_System_Sid = NULL ;
		ACCESS_ALLOWED_ACE *t_System_ACE = NULL ;
		WORD t_System_ACESize = 0 ;

		t_BoolResult = AllocateAndInitializeSid (

			& t_NtAuthoritySid ,
			1 ,
			SECURITY_LOCAL_SYSTEM_RID,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			& t_System_Sid
		);

		if ( t_BoolResult )
		{
			DWORD t_SidLength = ::GetLengthSid ( t_System_Sid );
			t_System_ACESize = sizeof(ACCESS_ALLOWED_ACE) + (WORD) ( t_SidLength - sizeof(DWORD) ) ;
			t_System_ACE = (ACCESS_ALLOWED_ACE*) new BYTE [ t_System_ACESize ] ;
			if ( t_System_ACE )
			{
				CopySid ( t_SidLength, (PSID) & t_System_ACE->SidStart, t_System_Sid ) ;
				t_System_ACE->Mask = 0x1F01FF;
				t_System_ACE->Header.AceType = 0 ;
				t_System_ACE->Header.AceFlags = 3 ;
				t_System_ACE->Header.AceSize = t_System_ACESize ;
			}
			else
			{
				t_Result = WBEM_E_OUT_OF_MEMORY ;
			}
		}
		else
		{
			DWORD t_LastError = ::GetLastError();

			t_Result = WBEM_E_OUT_OF_MEMORY ;
		}

		SID_IDENTIFIER_AUTHORITY t_WorldAuthoritySid = SECURITY_WORLD_SID_AUTHORITY ;

		PSID t_Everyone_Sid = NULL ;
		ACCESS_ALLOWED_ACE *t_Everyone_ACE = NULL ;
		USHORT t_Everyone_ACESize = 0 ;
		
		t_BoolResult = AllocateAndInitializeSid (

			& t_WorldAuthoritySid ,
			1 ,
			SECURITY_WORLD_RID ,
			0,
			0,
			0,
			0,
			0,
			0,
			0,
			& t_Everyone_Sid
		);

		if ( t_BoolResult )
		{
			DWORD t_SidLength = ::GetLengthSid ( t_Everyone_Sid );
			t_Everyone_ACESize = sizeof(ACCESS_ALLOWED_ACE) + (WORD) ( t_SidLength - sizeof(DWORD) ) ;
			t_Everyone_ACE = (ACCESS_ALLOWED_ACE*) new BYTE [ t_Everyone_ACESize ] ;
			if ( t_Everyone_ACE )
			{
				CopySid ( t_SidLength, (PSID) & t_Everyone_ACE->SidStart, t_Everyone_Sid ) ;
				t_Everyone_ACE->Mask = a_Access ;
				t_Everyone_ACE->Header.AceType = 0 ;
				t_Everyone_ACE->Header.AceFlags = 3 ;
				t_Everyone_ACE->Header.AceSize = t_Everyone_ACESize ;
			}
			else
			{
				t_Result = WBEM_E_OUT_OF_MEMORY ;
			}
		}
		else
		{
			DWORD t_LastError = ::GetLastError();

			t_Result = WBEM_E_OUT_OF_MEMORY ;
		}

		// Now we need to set permissions on the registry: Everyone read; Admins full.
		// We have the sid for admins from the above code.  Now get the sid for "Everyone"

		DWORD t_TotalAclSize = sizeof(ACL) + t_Administrator_ACESize + t_System_ACESize + t_Everyone_ACESize ;
		PACL t_Dacl = (PACL) new BYTE [ t_TotalAclSize ] ;
		if ( t_Dacl )
		{
			if ( :: InitializeAcl ( t_Dacl, t_TotalAclSize, ACL_REVISION ) )
			{
				DWORD t_AceIndex = 0 ;

				if ( t_System_ACESize && :: AddAce ( t_Dacl , ACL_REVISION , t_AceIndex , t_System_ACE , t_System_ACESize ) )
				{
					t_AceIndex ++ ;
				}
				
				if ( t_Administrator_ACESize && :: AddAce ( t_Dacl , ACL_REVISION , t_AceIndex , t_Administrator_ACE , t_Administrator_ACESize ) )
				{
					t_AceIndex ++ ;
				}

				if ( t_Everyone_ACESize && :: AddAce ( t_Dacl , ACL_REVISION, t_AceIndex , t_Everyone_ACE , t_Everyone_ACESize ) )
				{
					t_AceIndex ++ ;
				}

				t_BoolResult = SetSecurityDescriptorDacl (

				  & a_SecurityDescriptor ,
				  TRUE ,
				  t_Dacl ,
				  FALSE
				) ;

				if ( t_BoolResult == FALSE )
				{
					delete [] ( ( BYTE * ) t_Dacl ) ;

					t_Result = WBEM_E_CRITICAL_ERROR ;
				}
			}
		}
		else
		{
			t_Result = WBEM_E_OUT_OF_MEMORY ;
		}

		if ( t_Administrator_ACE )
		{
			delete [] ( ( BYTE * ) t_Administrator_ACE ) ;
		}

		if ( t_System_ACE )
		{
			delete [] ( ( BYTE * ) t_System_ACE ) ;
		}

		if ( t_Everyone_ACE )
		{
			delete [] ( ( BYTE * ) t_Everyone_ACE ) ;
		}

		if ( t_System_Sid )
		{
			FreeSid ( t_System_Sid ) ;
		}

		if ( t_Administrator_Sid )
		{
			FreeSid ( t_Administrator_Sid ) ;
		}

		if ( t_Everyone_Sid )
		{
			FreeSid ( t_Everyone_Sid ) ;
		}
	}
	else
	{
		t_Result = WBEM_E_CRITICAL_ERROR ;
	}

	return t_Result ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiOverlapped :: WmiOverlapped ( OverLappedType a_Type ) 
{
	ZeroMemory ( & m_Overlapped , sizeof ( m_Overlapped ) ) ;
	m_Type = a_Type ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiOverlapped :: ~WmiOverlapped ()
{
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiScheduledOverlapped :: WmiScheduledOverlapped ( 

	OverLappedType a_Type , 
	WmiIoScheduler &a_Scheduler

) : WmiOverlapped ( a_Type ) , 
	m_Scheduler ( a_Scheduler )
{
	m_Scheduler.AddRef () ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiScheduledOverlapped :: ~WmiScheduledOverlapped ()
{
	m_Scheduler.Release () ; 
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiTerminateOverlapped :: WmiTerminateOverlapped () : WmiOverlapped ( e_OverLapped_Terminate )
{
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiTaskOverlapped :: WmiTaskOverlapped (

	WmiIoScheduler &a_Scheduler ,
	WmiTaskOperation *a_OperationFunction

)	:	WmiScheduledOverlapped ( e_OverLapped_Task , a_Scheduler ) ,
		m_Status ( 0 ) ,
		m_State ( 0 ) ,
		m_OperationFunction ( a_OperationFunction )
{
	m_Overlapped.Offset = 0 ;
	m_Overlapped.OffsetHigh = 0 ;

	if ( m_OperationFunction )
	{
		m_OperationFunction->AddRef () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiTaskOverlapped :: ~WmiTaskOverlapped ()
{
	if ( m_OperationFunction )
	{
		m_OperationFunction->Release () ;
	}
}
/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiReadOverlapped :: WmiReadOverlapped (

	WmiIoScheduler &a_Scheduler ,
	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	BYTE *a_Buffer ,
	DWORD a_BufferSize 

)	:	WmiScheduledOverlapped ( e_OverLapped_Read , a_Scheduler ) ,
		m_Buffer ( a_Buffer ) ,
		m_BufferSize ( a_BufferSize ) ,
		m_Status ( 0 ) ,
		m_State ( 0 ) ,
		m_OperationFunction ( a_OperationFunction )
{
	m_Overlapped.Offset = a_OffSet & 0xFFFFFFFF ;
	m_Overlapped.OffsetHigh = a_OffSet >> 32 ;

	if ( m_OperationFunction )
	{
		m_OperationFunction->AddRef () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiReadOverlapped :: ~WmiReadOverlapped ()
{
	if ( m_OperationFunction )
	{
		m_OperationFunction->Release () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiWriteOverlapped :: WmiWriteOverlapped (

	WmiIoScheduler &a_Scheduler ,
	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	BYTE *a_Buffer ,
	DWORD a_BufferSize 

)	:	WmiScheduledOverlapped ( e_OverLapped_Write , a_Scheduler ) ,
		m_Buffer ( a_Buffer ) ,
		m_BufferSize ( a_BufferSize ) ,
		m_Status ( 0 ) ,
		m_State ( 0 ) ,
		m_OperationFunction ( a_OperationFunction )
{
	m_Overlapped.Offset = a_OffSet & 0xFFFFFFFF ;
	m_Overlapped.OffsetHigh = a_OffSet >> 32 ;

	if ( m_OperationFunction )
	{
		m_OperationFunction->AddRef () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiWriteOverlapped :: ~WmiWriteOverlapped ()
{
	if ( m_OperationFunction )
	{
		m_OperationFunction->Release () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiLockOverlapped :: WmiLockOverlapped (

	WmiIoScheduler &a_Scheduler ,
	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	WmiFileOffSet a_OffSetSize

)	:	WmiScheduledOverlapped ( e_OverLapped_Lock , a_Scheduler ) ,
		m_OffSetSize ( a_OffSetSize ) ,
		m_Status ( 0 ) ,
		m_State ( 0 ) ,
		m_OperationFunction ( a_OperationFunction )
{
	m_Overlapped.Offset = a_OffSet & 0xFFFFFFFF ;
	m_Overlapped.OffsetHigh = a_OffSet >> 32 ;

	if ( m_OperationFunction )
	{
		m_OperationFunction->AddRef () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiLockOverlapped :: ~WmiLockOverlapped ()
{
	if ( m_OperationFunction )
	{
		m_OperationFunction->Release () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiUnLockOverlapped :: WmiUnLockOverlapped (

	WmiIoScheduler &a_Scheduler ,
	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	WmiFileOffSet a_OffSetSize

)	:	WmiScheduledOverlapped ( e_OverLapped_UnLock , a_Scheduler ) ,
		m_OffSetSize ( a_OffSetSize ) ,
		m_Status ( 0 ) ,
		m_State ( 0 ) ,
		m_OperationFunction ( a_OperationFunction )
{
	m_Overlapped.Offset = a_OffSet & 0xFFFFFFFF ;
	m_Overlapped.OffsetHigh = a_OffSet >> 32 ;

	if ( m_OperationFunction )
	{
		m_OperationFunction->AddRef () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiUnLockOverlapped :: ~WmiUnLockOverlapped ()
{
	if ( m_OperationFunction )
	{
		m_OperationFunction->Release () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiCompletionPortOperation :: WmiCompletionPortOperation (

	WmiAllocator &a_Allocator ,
	WmiThreadPool *a_ThreadPool 

) : WmiTask <ULONG> ( a_Allocator ) ,
	m_ThreadPool ( a_ThreadPool ) 
{
	if ( m_ThreadPool )
	{
		m_ThreadPool->AddRef () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiCompletionPortOperation :: ~WmiCompletionPortOperation ()
{
	if ( m_ThreadPool )
	{
		m_ThreadPool->Release () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiCompletionPortOperation :: Process ( WmiThread <ULONG> &a_Thread )
{
	DWORD t_Continue = TRUE ;
	while ( t_Continue )
	{
		OVERLAPPED *t_Overlapped = NULL ;
		DWORD t_Key = 0 ;
		DWORD t_Bytes = 0 ;

		BOOL t_Status = GetQueuedCompletionStatus (

			m_ThreadPool->GetCompletionPort () ,
			& t_Bytes ,
			& t_Key ,
			& t_Overlapped ,
			INFINITE 
		) ;

		if ( t_Status )
		{
			WmiOverlapped *t_WmiOverlapped = ( WmiOverlapped * ) t_Overlapped ;
			switch ( t_WmiOverlapped->GetType () )
			{
				case WmiOverlapped :: OverLappedType :: e_OverLapped_Terminate:
				{
					WmiTerminateOverlapped *t_TerminateOverlapped = ( WmiTerminateOverlapped * ) t_Overlapped ;
					delete t_TerminateOverlapped ;
					t_Continue = FALSE ;
				}
				break ;

				case WmiOverlapped :: OverLappedType :: e_OverLapped_Task:
				{
					WmiTaskOverlapped *t_TaskOverlapped = ( WmiTaskOverlapped * ) t_Overlapped ;
					WmiIoScheduler &t_Allocator = t_TaskOverlapped->GetScheduler () ;

					t_Allocator.TaskBegin ( t_TaskOverlapped ) ;
				}
				break ;

				case WmiOverlapped :: OverLappedType :: e_OverLapped_Read:
				{
					WmiReadOverlapped *t_ReadOverlapped = ( WmiReadOverlapped * ) t_Overlapped ;
					WmiIoScheduler &t_Allocator = t_ReadOverlapped->GetScheduler () ;

					switch ( t_ReadOverlapped->GetState () )
					{
						case 0:
						{
							t_Allocator.ReadBegin ( t_ReadOverlapped , t_Bytes ) ;
						}
						break ;

						case 1:
						{
							t_Allocator.ReadComplete ( t_ReadOverlapped , t_Bytes ) ;
						}

						default:
						{
						}
						break ;
					}
				}
				break ;

				case WmiOverlapped :: OverLappedType :: e_OverLapped_Lock:
				{
					WmiLockOverlapped *t_LockOverlapped = ( WmiLockOverlapped * ) t_Overlapped ;
					WmiIoScheduler &t_Allocator = t_LockOverlapped->GetScheduler () ;

					switch ( t_LockOverlapped->GetState () )
					{
						case 0:
						{
							t_Allocator.LockBegin ( t_LockOverlapped , t_Bytes ) ;
						}
						break ;

						case 1:
						{
							t_Allocator.LockComplete ( t_LockOverlapped , t_Bytes ) ;
						}

						default:
						{
						}
						break ;
					}
				}
				break ;

				case WmiOverlapped :: OverLappedType :: e_OverLapped_UnLock:
				{
					WmiUnLockOverlapped *t_UnLockOverlapped = ( WmiUnLockOverlapped * ) t_Overlapped ;
					WmiIoScheduler &t_Allocator = t_UnLockOverlapped->GetScheduler () ;

					switch ( t_UnLockOverlapped->GetState () )
					{
						case 0:
						{
							t_Allocator.UnLockBegin ( t_UnLockOverlapped , t_Bytes ) ;
						}
						break ;

						case 1:
						{
							t_Allocator.UnLockComplete ( t_UnLockOverlapped , t_Bytes ) ;
						}

						default:
						{
						}
						break ;
					}
				}
				break ;

				case WmiOverlapped :: OverLappedType :: e_OverLapped_Write:
				{
					WmiWriteOverlapped *t_WriteOverlapped = ( WmiWriteOverlapped * ) t_Overlapped ;
					WmiIoScheduler &t_Allocator = t_WriteOverlapped->GetScheduler ()  ;

					switch ( t_WriteOverlapped->GetState () )
					{
						case 0:
						{
							t_Allocator.WriteBegin ( t_WriteOverlapped , t_Bytes ) ;
						}
						break ;

						case 1:
						{
							t_Allocator.WriteComplete ( t_WriteOverlapped , t_Bytes ) ;
						}

						default:
						{
						}
						break ;
					}
				}
				break ;

				default:
				{
					t_Continue = FALSE ;
				}
				break ;
			}
		}
		else
		{
			DWORD t_LastError = GetLastError () ;

			if ( t_Overlapped == NULL )
			{
				break ;
			}
		}
	}

	Complete () ;

	return e_StatusCode_Success ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/
	
WmiThreadPool :: WmiThreadPool ( 

	WmiAllocator &a_Allocator ,
	const ULONG &a_Threads 

) : m_Allocator ( a_Allocator ) ,
	m_ReferenceCount ( 0 ) ,
	m_ThreadPool ( NULL ) ,
	m_CompletionPort ( NULL )
{
	if ( a_Threads == 0 )
	{
		SYSTEM_INFO t_SystemInformation ;
		GetSystemInfo ( & t_SystemInformation ) ;

		m_Threads = t_SystemInformation.dwNumberOfProcessors ;
	}
	else
	{
		m_Threads = a_Threads ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiThreadPool :: ~WmiThreadPool ()
{
	UnInitialize () ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

ULONG WmiThreadPool :: AddRef () 
{
	return InterlockedIncrement ( & m_ReferenceCount ) ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

ULONG WmiThreadPool :: Release () 
{
	ULONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
	if ( t_ReferenceCount == 0 )
	{
		delete this ;
	}

	return t_ReferenceCount ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiThreadPool :: Initialize ()
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	t_StatusCode = WmiThread <ULONG> :: Static_Initialize ( m_Allocator ) ;
	if ( t_StatusCode == e_StatusCode_Success )
	{
		m_CompletionPort = CreateIoCompletionPort (

			INVALID_HANDLE_VALUE ,
			NULL ,
			NULL ,
			0
		) ;

		if ( m_CompletionPort == NULL )
		{
			t_StatusCode = e_StatusCode_OutOfResources ;
		}

		if ( t_StatusCode == e_StatusCode_Success )
		{
			m_ThreadPool = new WmiThread <ULONG> * [ m_Threads ] ;
			if ( m_ThreadPool )
			{
				for ( ULONG t_Index = 0 ; t_Index < m_Threads ; t_Index ++ )
				{
					m_ThreadPool [ t_Index ] = new WmiThread <ULONG> ( m_Allocator ) ;
					if ( m_ThreadPool [ t_Index ] ) 
					{
						m_ThreadPool [ t_Index ]->AddRef () ;

						t_StatusCode = m_ThreadPool [ t_Index ]->Initialize () ;
						if ( t_StatusCode == e_StatusCode_Success )
						{
							WmiCompletionPortOperation *t_Operation = new WmiCompletionPortOperation ( 

								m_Allocator , 
								this
							) ;

							if ( t_Operation )
							{
								t_StatusCode = t_Operation->Initialize () ;
								if ( t_StatusCode == e_StatusCode_Success )					
								{
									m_ThreadPool [ t_Index ]->EnQueue ( 0 , *t_Operation ) ;
								}
							}
						}
					}
					else
					{
						t_StatusCode = e_StatusCode_OutOfMemory ;
					}
				}
			}
			else
			{
				t_StatusCode = e_StatusCode_OutOfMemory ;
			}
		}
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiThreadPool :: UnInitialize ()
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	if ( m_ThreadPool )
	{
		for ( ULONG t_Index = 0 ; t_Index < m_Threads ; t_Index ++ )
		{
			if ( m_ThreadPool [ t_Index ] ) 
			{
				WmiTerminateOverlapped *t_Terminate = new WmiTerminateOverlapped ;
				if ( t_Terminate )
				{
					BOOL t_Status = PostQueuedCompletionStatus ( 

						GetCompletionPort () ,
						0 ,
						NULL ,
						( OVERLAPPED * ) t_Terminate 
					) ;

					if ( t_Status )
					{
						HANDLE t_ThreadHandle = NULL ;

						BOOL t_Status = DuplicateHandle ( 

							GetCurrentProcess () ,
							m_ThreadPool [ t_Index ]->GetHandle () ,
							GetCurrentProcess () ,
							& t_ThreadHandle, 
							0 , 
							FALSE , 
							DUPLICATE_SAME_ACCESS
						) ;

						m_ThreadPool [ t_Index ]->Release () ;

						WaitForSingleObject ( t_ThreadHandle , INFINITE ) ;

						CloseHandle ( t_ThreadHandle ) ;
					}
					else
					{
						t_StatusCode = e_StatusCode_Failed ;
					}
				}
			}
		}

		delete [] m_ThreadPool ;
		m_ThreadPool = NULL ;
	}

	if ( m_CompletionPort )
	{
		CloseHandle ( m_CompletionPort ) ;
	}
	
	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/
	
WmiIoScheduler :: WmiIoScheduler ( 

	WmiAllocator &a_Allocator ,
	WmiThreadPool *a_ThreadPool ,
	wchar_t *a_FileName ,
	WmiFileSize a_InitialSize , 
	WmiFileSize a_MaximumSize

) : m_Allocator ( a_Allocator ) ,
	m_InitialSize ( a_InitialSize ) ,
	m_MaximumSize ( a_MaximumSize ) ,
	m_ReferenceCount ( 0 ) ,
	m_ThreadPool ( a_ThreadPool ) ,
	m_FileHandle ( NULL ) ,
	m_FileName ( NULL )
{
	m_FileName = new wchar_t [ wcslen ( a_FileName ) + 1 ] ;
	if ( m_FileName ) 
	{
		wcscpy ( m_FileName , a_FileName ) ;
	}

	if ( m_ThreadPool )
	{
		m_ThreadPool->AddRef () ;
	}
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiIoScheduler :: ~WmiIoScheduler ()
{
	UnInitialize () ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

ULONG WmiIoScheduler :: AddRef () 
{
	return InterlockedIncrement ( & m_ReferenceCount ) ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

ULONG WmiIoScheduler :: Release () 
{
	ULONG t_ReferenceCount = InterlockedDecrement ( & m_ReferenceCount ) ;
	if ( t_ReferenceCount == 0 )
	{
		delete this ;
	}

	return t_ReferenceCount ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Initialize ()
{
	WmiStatusCode t_StatusCode = Create () ;
	if ( t_StatusCode == e_StatusCode_Success )
	{
		HANDLE t_CompletionPort = CreateIoCompletionPort (

			m_FileHandle ,
			m_ThreadPool->GetCompletionPort () ,
			( ULONG_PTR ) this ,
			0
		) ;

		if ( t_CompletionPort != INVALID_HANDLE_VALUE )
		{
		}
		else
		{
			t_StatusCode = Win32ToApi () ;
		}
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: UnInitialize ()
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	if ( m_FileName ) 
	{
		delete [] m_FileName ;
		m_FileName = NULL ;
	}

	t_StatusCode = Close () ;

	if ( m_ThreadPool )
	{
		m_ThreadPool->Release () ;
		m_ThreadPool = NULL ;
	}
	
	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Task ( 

	WmiTaskOperation *a_OperationFunction
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiTaskOverlapped *t_Overlapped = new WmiTaskOverlapped (

		*this ,
		a_OperationFunction 
	) ;

	if ( t_Overlapped )
	{
		BOOL t_Status = PostQueuedCompletionStatus ( 

			m_ThreadPool->GetCompletionPort () ,
			0 ,
			( ULONG_PTR ) this ,
			( OVERLAPPED * ) t_Overlapped
		) ;

		if ( t_Status == FALSE ) 
		{
			t_StatusCode = Win32ToApi () ;
		}
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Read ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	BYTE *a_ReadBytes ,
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiReadOverlapped *t_Overlapped = new WmiReadOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_ReadBytes ,
		a_Bytes
	) ;

	if ( t_Overlapped )
	{
		BOOL t_Status = PostQueuedCompletionStatus ( 

			m_ThreadPool->GetCompletionPort () ,
			a_Bytes ,
			( ULONG_PTR ) this ,
			( OVERLAPPED * ) t_Overlapped
		) ;

		if ( t_Status == FALSE ) 
		{
			t_StatusCode = Win32ToApi () ;
		}
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Write ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	BYTE *a_WriteBytes ,
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiWriteOverlapped *t_Overlapped = new WmiWriteOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_WriteBytes ,
		a_Bytes
	) ;

	if ( t_Overlapped )
	{
		BOOL t_Status = PostQueuedCompletionStatus ( 

			m_ThreadPool->GetCompletionPort () ,
			a_Bytes ,
			( ULONG_PTR ) this ,
			( OVERLAPPED * ) t_Overlapped
		) ;

		if ( t_Status == FALSE ) 
		{
			t_StatusCode = Win32ToApi () ;
		}
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Lock ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	WmiFileOffSet a_OffSetSize
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiLockOverlapped *t_Overlapped = new WmiLockOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_OffSetSize
	) ;

	if ( t_Overlapped )
	{
		BOOL t_Status = PostQueuedCompletionStatus ( 

			m_ThreadPool->GetCompletionPort () ,
			0 ,
			( ULONG_PTR ) this ,
			( OVERLAPPED * ) t_Overlapped
		) ;

		if ( t_Status == FALSE ) 
		{
			t_StatusCode = Win32ToApi () ;
		}
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: UnLock ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	WmiFileOffSet a_OffSetSize
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiUnLockOverlapped *t_Overlapped = new WmiUnLockOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_OffSetSize
	) ;

	if ( t_Overlapped )
	{
		BOOL t_Status = PostQueuedCompletionStatus ( 

			m_ThreadPool->GetCompletionPort () ,
			0 ,
			( ULONG_PTR ) this ,
			( OVERLAPPED * ) t_Overlapped
		) ;

		if ( t_Status == FALSE ) 
		{
			t_StatusCode = Win32ToApi () ;
		}
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: ReadOnThread ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	BYTE *a_ReadBytes ,
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiReadOverlapped *t_Overlapped = new WmiReadOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_ReadBytes ,
		a_Bytes
	) ;

	if ( t_Overlapped )
	{
		t_Overlapped->SetState ( 1 ) ;

		t_StatusCode = ReadBegin (

			t_Overlapped ,
			0
		) ;
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: WriteOnThread ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	BYTE *a_WriteBytes ,
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiWriteOverlapped *t_Overlapped = new WmiWriteOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_WriteBytes ,
		a_Bytes
	) ;

	if ( t_Overlapped )
	{
		t_Overlapped->SetState ( 1 ) ;

		t_StatusCode = WriteBegin (

			t_Overlapped ,
			0
		) ;
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: LockOnThread ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	WmiFileOffSet a_OffSetSize
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiLockOverlapped *t_Overlapped = new WmiLockOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_OffSetSize
	) ;

	if ( t_Overlapped )
	{
		t_Overlapped->SetState ( 1 ) ;

		t_StatusCode = LockBegin (

			t_Overlapped ,
			0 
		) ;
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: TaskBegin ( 

	WmiTaskOverlapped *a_Overlapped
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	a_Overlapped->SetState ( 1 ) ;

	a_Overlapped->GetOperationFunction ()->Operation ( 

		t_StatusCode
	) ;

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: UnLockOnThread ( 

	WmiFileOperation *a_OperationFunction ,
	WmiFileOffSet a_OffSet ,
	WmiFileOffSet a_OffSetSize
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	WmiUnLockOverlapped *t_Overlapped = new WmiUnLockOverlapped (

		*this ,
		a_OperationFunction ,
		a_OffSet ,
		a_OffSetSize
	) ;

	if ( t_Overlapped )
	{
		t_Overlapped->SetState ( 1 ) ;

		t_StatusCode = UnLockBegin (

			t_Overlapped ,
			0 
		) ;
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfMemory ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: ReadBegin ( 

	WmiReadOverlapped *a_Overlapped , 
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	a_Overlapped->SetState ( 1 ) ;

	DWORD t_Bytes = 0 ;

	t_StatusCode = Read (

		a_Overlapped->GetBuffer () ,
		a_Overlapped->GetBufferSize () ,
		& t_Bytes ,
		( OVERLAPPED * ) a_Overlapped 
	) ;

	if ( t_StatusCode == e_StatusCode_Success ) 
	{
	}
	else
	{
		a_Overlapped->GetOperationFunction ()->Operation ( 

			t_StatusCode ,
			a_Overlapped->GetBuffer () ,
			a_Overlapped->GetBufferSize ()
		) ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: WriteBegin ( 

	WmiWriteOverlapped *a_Overlapped , 
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	a_Overlapped->SetState ( 1 ) ;

	DWORD t_Bytes = 0 ;

	t_StatusCode = Write (

		a_Overlapped->GetBuffer () ,
		a_Overlapped->GetBufferSize () ,
		& t_Bytes ,
		( OVERLAPPED * ) a_Overlapped 
	) ;

	if ( t_StatusCode == e_StatusCode_Success ) 
	{
	}
	else
	{
		a_Overlapped->GetOperationFunction ()->Operation ( 

			t_StatusCode ,
			a_Overlapped->GetBuffer () ,
			a_Overlapped->GetBufferSize ()
		) ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: LockBegin ( 

	WmiLockOverlapped *a_Overlapped , 
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	a_Overlapped->SetState ( 1 ) ;

	t_StatusCode = Lock (

		LOCKFILE_EXCLUSIVE_LOCK ,
		a_Overlapped->GetOffSetSize () & 0xFFFFFFFF ,
		a_Overlapped->GetOffSetSize () >> 32 ,
		( OVERLAPPED * ) a_Overlapped 
	) ;

	if ( t_StatusCode == e_StatusCode_Success ) 
	{
	}
	else
	{
		a_Overlapped->GetOperationFunction ()->Operation ( 

			t_StatusCode ,
			NULL ,
			0
		) ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: UnLockBegin ( 

	WmiUnLockOverlapped *a_Overlapped , 
	DWORD a_Bytes
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	a_Overlapped->SetState ( 1 ) ;

	t_StatusCode = UnLock (

		a_Overlapped->GetOffSetSize () & 0xFFFFFFFF ,
		a_Overlapped->GetOffSetSize () >> 32 ,
		( OVERLAPPED * ) a_Overlapped 
	) ;

	if ( t_StatusCode == e_StatusCode_Success ) 
	{
	}
	else
	{
		t_StatusCode = Win32ToApi () ;

		a_Overlapped->GetOperationFunction ()->Operation ( 

			t_StatusCode ,
			NULL ,
			0
		) ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

void WmiIoScheduler :: ReadComplete ( WmiReadOverlapped *a_Overlapped , DWORD a_Bytes )
{
	a_Overlapped->GetOperationFunction ()->Operation ( 

		a_Overlapped->GetStatus () ,
		a_Overlapped->GetBuffer () ,
		a_Overlapped->GetBufferSize ()
	) ;

	delete a_Overlapped ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

void WmiIoScheduler :: WriteComplete ( WmiWriteOverlapped *a_Overlapped , DWORD a_Bytes )
{
	a_Overlapped->GetOperationFunction ()->Operation ( 

		a_Overlapped->GetStatus () ,
		a_Overlapped->GetBuffer () ,
		a_Overlapped->GetBufferSize ()
	) ;

	delete a_Overlapped ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

void WmiIoScheduler :: LockComplete ( WmiLockOverlapped *a_Overlapped , DWORD a_Bytes )
{
	a_Overlapped->GetOperationFunction ()->Operation ( 

		a_Overlapped->GetStatus () ,
		NULL ,
		0
	) ;

	delete a_Overlapped ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

void WmiIoScheduler :: UnLockComplete ( WmiUnLockOverlapped *a_Overlapped , DWORD a_Bytes )
{
	a_Overlapped->GetOperationFunction ()->Operation ( 

		a_Overlapped->GetStatus () ,
		NULL ,
		0
	) ;

	delete a_Overlapped ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: SetFileExtent (

	const WmiFileOffSet &a_FileOffSet 
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	LARGE_INTEGER t_Integer ;
	t_Integer.QuadPart = a_FileOffSet ;

	BOOL t_Status = SetFilePointerEx ( 

		GetFileHandle () ,
		t_Integer ,
		NULL ,
		FILE_END 
	) ;

	if ( t_Status )
	{
		t_Status = SetEndOfFile ( GetFileHandle () ) ;
		if ( t_Status == FALSE )
		{
			t_StatusCode = e_StatusCode_OutOfResources ;
		}
	}
	else
	{
		t_StatusCode = e_StatusCode_OutOfResources ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Create ()
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	if ( m_FileName ) 
	{
		SECURITY_DESCRIPTOR t_SecurityDescriptor ;

		HRESULT t_Result = GetSecurityDescriptor ( t_SecurityDescriptor , 0 ) ;
		if ( SUCCEEDED ( t_Result ) )
		{
			SECURITY_ATTRIBUTES t_SecurityAttributes ;

			t_SecurityAttributes.nLength = sizeof ( SECURITY_ATTRIBUTES ) ; 
			t_SecurityAttributes.lpSecurityDescriptor = & t_SecurityDescriptor ; 
			t_SecurityAttributes.bInheritHandle = FALSE ; 

#if 0
			m_FileHandle = CreateFile ( 

				m_FileName ,
				GENERIC_READ | GENERIC_WRITE | MAXIMUM_ALLOWED ,
				0 ,
				& t_SecurityAttributes ,
				OPEN_ALWAYS ,
				FILE_FLAG_OVERLAPPED | FILE_FLAG_RANDOM_ACCESS ,
				NULL 
			) ;
#else
			m_FileHandle = CreateFile ( 

				m_FileName ,
				GENERIC_READ | GENERIC_WRITE | MAXIMUM_ALLOWED ,
				FILE_SHARE_READ | FILE_SHARE_WRITE ,
				NULL ,
				OPEN_ALWAYS ,
				FILE_FLAG_OVERLAPPED | FILE_FLAG_RANDOM_ACCESS ,
				NULL 
			) ;

#endif
			if ( m_FileHandle != INVALID_HANDLE_VALUE )
			{
			}
			else
			{
				t_StatusCode = Win32ToApi () ;
			}

			delete [] t_SecurityDescriptor.Dacl ;
		}
		else
		{
			t_StatusCode = e_StatusCode_OutOfMemory ;
		}
	}
	else
	{
		t_StatusCode = e_StatusCode_InvalidArgs ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Close ()
{
	if ( m_FileHandle ) 
	{
		CloseHandle ( m_FileHandle ) ;
		m_FileHandle = 0 ;
	}

	return e_StatusCode_Success ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Read (

	LPVOID a_Buffer ,
	DWORD a_NumberOfBytesToRead ,
	LPDWORD a_NumberOfBytesRead ,
	LPOVERLAPPED a_Overlapped
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	DWORD t_Bytes = 0 ;

	BOOL t_Status = ReadFile (

		m_FileHandle ,
		a_Buffer ,
		a_NumberOfBytesToRead ,
		a_NumberOfBytesRead ,
		( OVERLAPPED * ) a_Overlapped 
	) ;

	if ( t_Status ) 
	{
	}
	else
	{
		t_StatusCode = Win32ToApi () ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Write (

	LPVOID a_Buffer ,
	DWORD a_NumberOfBytesToWrite ,
	LPDWORD a_NumberOfBytesWritten ,
	LPOVERLAPPED a_Overlapped
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	BOOL t_Status = WriteFile (

		m_FileHandle ,
		a_Buffer ,
		a_NumberOfBytesToWrite ,
		a_NumberOfBytesWritten ,
		a_Overlapped
	) ;

	if ( t_Status ) 
	{
	}
	else
	{
		t_StatusCode = Win32ToApi () ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: Lock (

	DWORD a_Flags ,
	DWORD a_NumberOfBytesToLockLow ,
	DWORD a_NumberOfBytesToLockHigh ,
	LPOVERLAPPED a_Overlapped       
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	BOOL t_Status = LockFileEx (

		m_FileHandle ,
		a_Flags ,
		0 ,
		a_NumberOfBytesToLockLow ,
		a_NumberOfBytesToLockHigh ,
		a_Overlapped       
	) ;

	if ( t_Status ) 
	{
	}
	else
	{
		t_StatusCode = Win32ToApi () ;
	}

	return t_StatusCode ;
}

/******************************************************************************
 *
 *	Name:
 *
 *	
 *  Description:
 *
 *	
 *****************************************************************************/

WmiStatusCode WmiIoScheduler :: UnLock (

	DWORD a_NumberOfBytesToUnlockLow ,
	DWORD a_NumberOfBytesToUnlockHigh ,
	LPOVERLAPPED a_Overlapped
)
{
	WmiStatusCode t_StatusCode = e_StatusCode_Success ;

	BOOL t_Status = UnlockFileEx (

		m_FileHandle ,
		0 ,
		a_NumberOfBytesToUnlockLow ,
		a_NumberOfBytesToUnlockHigh ,
		a_Overlapped 
	) ;

	if ( t_Status ) 
	{
	}
	else
	{
		t_StatusCode = Win32ToApi () ;
	}

	return t_StatusCode ;	
}