windows-nt/Source/XPSP1/NT/admin/wmi/wbem/common/containers/ioscheduler.cpp

2286 lines
42 KiB
C++
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*
* 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 ;
}