/* * Class: * * WmiIoScheduler * * Description: * * Provides abstraction above heap allocation functions * * Version: * * Initial * * Last Changed: * * See Source Depot for change history * */ #include #include #include #include #include #include #include /****************************************************************************** * * 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 ( 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 &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 :: 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 * [ m_Threads ] ; if ( m_ThreadPool ) { for ( ULONG t_Index = 0 ; t_Index < m_Threads ; t_Index ++ ) { m_ThreadPool [ t_Index ] = new WmiThread ( 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 ; }