wince.c
来自「cryptlib安全工具包」· C语言 代码 · 共 526 行 · 第 1/2 页
C
526 行
/* Make sure we got valid pointers for every Toolhelp32 function */
if( pModule32First == NULL || pModule32Next == NULL || \
pProcess32First == NULL || pProcess32Next == NULL || \
pThread32First == NULL || pThread32Next == NULL || \
pHeap32ListFirst == NULL || pHeap32ListNext == NULL || \
pHeap32First == NULL || pHeap32Next == NULL || \
pCreateToolhelp32Snapshot == NULL )
{
/* Mark the main function as unavailable in case for future
reference */
pCreateToolhelp32Snapshot = NULL;
return;
}
}
if( krnlIsExiting() )
return;
initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );
/* Take snapshots what's currently in the system. In theory we could
do a TH32CS_SNAPALL to get everything at once, but this can lead
to out-of-memory errors on some memory-limited systems, so we only
snapshot the individual resource that we're interested in.
First we walk through the local heap. We have to be careful to not
spend excessive amounts of time on this if we're linked into a large
application with a great many heaps and/or heap blocks, since the
heap-traversal functions are rather slow. Fortunately this is
quite rare under WinCE since it implies a large/long-running server
app, which we're unlikely to run into.
Ideally in order to prevent excessive delays we'd count the number
of heaps and ensure that no_heaps * no_heap_blocks doesn't exceed
some maximum value, however this requires two passes of (slow) heap
traversal rather than one, which doesn't help the situation much.
To provide at least some protection, we limit the total number of
heaps and heap entries traversed, although this leads to slightly
suboptimal performance if we have a small number of deep heaps
rather than the current large number of shallow heaps.
There is however a second consideration that needs to be taken into
account when doing this, which is that the heap-management functions
aren't completely thread-safe, so that under (very rare) conditions
of heavy allocation/deallocation this can cause problems when calling
HeapNext(). By limiting the amount of time that we spend in each
heap, we can reduce our exposure somewhat */
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPHEAPLIST, 0 );
if( hSnapshot == INVALID_HANDLE_VALUE )
{
assert( DEBUG_WARN ); /* Make sure that we get some feedback */
return;
}
hl32.dwSize = sizeof( HEAPLIST32 );
if( pHeap32ListFirst( hSnapshot, &hl32 ) )
do
{
HEAPENTRY32 he32;
int entryCount = 0;
/* First add the information from the basic Heaplist32
structure */
if( krnlIsExiting() )
{
pCloseToolhelp32Snapshot( hSnapshot );
return;
}
addRandomData( randomState, &hl32, sizeof( HEAPLIST32 ) );
/* Now walk through the heap blocks getting information
on each of them */
he32.dwSize = sizeof( HEAPENTRY32 );
if( pHeap32First( hSnapshot, &he32, hl32.th32ProcessID, hl32.th32HeapID ) )
do
{
if( krnlIsExiting() )
{
pCloseToolhelp32Snapshot( hSnapshot );
return;
}
addRandomData( randomState, &he32,
sizeof( HEAPENTRY32 ) );
}
while( entryCount++ < 20 && pHeap32Next( hSnapshot, &he32 ) );
}
while( listCount++ < 20 && pHeap32ListNext( hSnapshot, &hl32 ) );
pCloseToolhelp32Snapshot( hSnapshot );
if( krnlIsExiting() )
return;
/* Now walk through all processes */
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPPROCESS, 0 );
if( hSnapshot == INVALID_HANDLE_VALUE )
{
endRandomData( randomState, 40 );
return;
}
pe32.dwSize = sizeof( PROCESSENTRY32 );
iterationCount = 0;
if( pProcess32First( hSnapshot, &pe32 ) )
do
{
if( krnlIsExiting() )
{
pCloseToolhelp32Snapshot( hSnapshot );
return;
}
addRandomData( randomState, &pe32, sizeof( PROCESSENTRY32 ) );
}
while( pProcess32Next( hSnapshot, &pe32 ) && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
pCloseToolhelp32Snapshot( hSnapshot );
if( krnlIsExiting() )
return;
/* Then walk through all threads */
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPTHREAD, 0 );
if( hSnapshot == INVALID_HANDLE_VALUE )
{
endRandomData( randomState, 60 );
return;
}
te32.dwSize = sizeof( THREADENTRY32 );
iterationCount = 0;
if( pThread32First( hSnapshot, &te32 ) )
do
{
if( krnlIsExiting() )
{
pCloseToolhelp32Snapshot( hSnapshot );
return;
}
addRandomData( randomState, &te32, sizeof( THREADENTRY32 ) );
}
while( pThread32Next( hSnapshot, &te32 ) && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
pCloseToolhelp32Snapshot( hSnapshot );
if( krnlIsExiting() )
return;
/* Finally, walk through all modules associated with the process */
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPMODULE, 0 );
if( hSnapshot == INVALID_HANDLE_VALUE )
{
endRandomData( randomState, 80 );
return;
}
me32.dwSize = sizeof( MODULEENTRY32 );
iterationCount = 0;
if( pModule32First( hSnapshot, &me32 ) )
do
{
if( krnlIsExiting() )
{
pCloseToolhelp32Snapshot( hSnapshot );
return;
}
addRandomData( randomState, &me32, sizeof( MODULEENTRY32 ) );
}
while( pModule32Next( hSnapshot, &me32 ) && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
pCloseToolhelp32Snapshot( hSnapshot );
if( krnlIsExiting() )
return;
/* Flush any remaining data through */
endRandomData( randomState, 100 );
}
/* Perform a thread-safe slow poll for Windows CE */
DWORD WINAPI threadSafeSlowPoll( void *dummy )
{
UNUSED_ARG( dummy );
slowPollWinCE();
ExitThread( 0 );
return( 0 );
}
/* Perform a generic slow poll. This starts the OS-specific poll in a
separate thread */
void slowPoll( void )
{
if( krnlIsExiting() )
return;
/* Start a threaded slow poll. If a slow poll is already running, we
just return since there isn't much point in running two of them at the
same time */
if( hThread )
return;
hThread = CreateThread( NULL, 0, threadSafeSlowPoll, NULL, 0, &threadID );
assert( hThread );
}
/* Wait for the randomness gathering to finish. Anything that requires the
gatherer process to have completed gathering entropy should call
waitforRandomCompletion(), which will block until the background process
completes */
int waitforRandomCompletion( const BOOLEAN force )
{
DWORD dwResult;
const DWORD timeout = force ? 2000 : 300000L;
int status;
/* If there's no polling thread running, there's nothing to do. Note
that this isn't entirely thread-safe because someone may start
another poll after we perform this check, but there's no way to
handle this without some form of interlock mechanism with the
randomness mutex and the WaitForSingleObject(). In any case all
that'll happen is that the caller won't get all of the currently-
polling entropy */
if( hThread == NULL )
return( CRYPT_OK );
/* Wait for the polling thread to terminate. If it's a forced shutdown
we only wait a short amount of time (2s) before we bail out,
otherwise we hang around for as long as it takes (with a sanity-check
upper limit of 5 minutes) */
dwResult = WaitForSingleObject( hThread, timeout );
if( dwResult == WAIT_FAILED )
{
/* Since this is a cleanup function there's not much that we can do
at this point, although we warn in debug mode */
assert( DEBUG_WARN );
return( CRYPT_OK );
}
assert( dwResult != WAIT_FAILED ); /* Warn in debug mode */
/* Clean up */
status = krnlEnterMutex( MUTEX_RANDOM );
if( cryptStatusError( status ) )
return( status );
if( hThread != NULL )
{
CloseHandle( hThread );
hThread = NULL;
}
krnlExitMutex( MUTEX_RANDOM );
return( CRYPT_OK );
}
/* Initialise and clean up any auxiliary randomness-related objects */
void initRandomPolling( void )
{
/* Reset the various object handles and status info */
hToolHelp32 = hThread = NULL;
}
void endRandomPolling( void )
{
assert( hThread == NULL );
if( hToolHelp32 )
{
FreeLibrary( hToolHelp32 );
hToolHelp32 = NULL;
}
}
⌨️ 快捷键说明
复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?