📄 win32.c
字号:
xor eax, eax
xor edx, edx /* Tell VC++ that EDX:EAX will be trashed */
mov ecx, 0x58002006 /* GLD_MSR_CTRL */
rdmsr
and eax, 0110000000000b
cmp eax, 0010000000000b /* Check whether TRNG is enabled */
jne trngDisabled /* TRNG isn't enabled */
trngDisabled:
}
if( value )
addRandomValue( randomState, value );
}
#endif /* NO_ASM */
/* Flush any remaining data through. Quality = int( 33 1/3 % ) */
endRandomData( randomState, 34 );
}
/****************************************************************************
* *
* Slow Poll *
* *
****************************************************************************/
/* Type definitions for function pointers to call Toolhelp32 functions */
typedef BOOL ( WINAPI *MODULEWALK )( HANDLE hSnapshot, LPMODULEENTRY32 lpme );
typedef BOOL ( WINAPI *THREADWALK )( HANDLE hSnapshot, LPTHREADENTRY32 lpte );
typedef BOOL ( WINAPI *PROCESSWALK )( HANDLE hSnapshot, LPPROCESSENTRY32 lppe );
typedef BOOL ( WINAPI *HEAPLISTWALK )( HANDLE hSnapshot, LPHEAPLIST32 lphl );
typedef BOOL ( WINAPI *HEAPFIRST )( LPHEAPENTRY32 lphe, DWORD th32ProcessID, DWORD th32HeapID );
typedef BOOL ( WINAPI *HEAPNEXT )( LPHEAPENTRY32 lphe );
typedef HANDLE ( WINAPI *CREATESNAPSHOT )( DWORD dwFlags, DWORD th32ProcessID );
/* Global function pointers. These are necessary because the functions need to
be dynamically linked since only the Win95 kernel currently contains them.
Explicitly linking to them will make the program unloadable under NT */
static CREATESNAPSHOT pCreateToolhelp32Snapshot = NULL;
static MODULEWALK pModule32First = NULL;
static MODULEWALK pModule32Next = NULL;
static PROCESSWALK pProcess32First = NULL;
static PROCESSWALK pProcess32Next = NULL;
static THREADWALK pThread32First = NULL;
static THREADWALK pThread32Next = NULL;
static HEAPLISTWALK pHeap32ListFirst = NULL;
static HEAPLISTWALK pHeap32ListNext = NULL;
static HEAPFIRST pHeap32First = NULL;
static HEAPNEXT pHeap32Next = NULL;
/* Since there are a significant number of ToolHelp data blocks, we use a
larger-than-usual intermediate buffer to cut down on kernel traffic */
#define BIG_RANDOM_BUFSIZE ( RANDOM_BUFSIZE * 4 )
#if BIG_RANDOM_BUFSIZE > MAX_INTLENGTH_SHORT
#error BIG_RANDOM_BUFSIZE exceeds randomness accumulator size
#endif /* RANDOM_BUFSIZE > MAX_INTLENGTH_SHORT */
static void slowPollWin95( void )
{
static BOOLEAN addedFixedItems = FALSE;
PROCESSENTRY32 pe32;
THREADENTRY32 te32;
MODULEENTRY32 me32;
HEAPLIST32 hl32;
HANDLE hSnapshot;
RANDOM_STATE randomState;
BYTE buffer[ BIG_RANDOM_BUFSIZE + 8 ];
int listCount = 0, iterationCount, status;
/* The following are fixed for the lifetime of the process so we only
add them once */
if( !addedFixedItems )
{
readPnPData();
addedFixedItems = TRUE;
}
/* Initialize the Toolhelp32 function pointers if necessary */
if( pCreateToolhelp32Snapshot == NULL )
{
HANDLE hKernel;
/* Obtain the module handle of the kernel to retrieve the addresses
of the Toolhelp32 functions */
if( ( hKernel = GetModuleHandle( "Kernel32.dll" ) ) == NULL )
return;
/* Now get pointers to the functions */
pCreateToolhelp32Snapshot = ( CREATESNAPSHOT ) GetProcAddress( hKernel,
"CreateToolhelp32Snapshot" );
pModule32First = ( MODULEWALK ) GetProcAddress( hKernel,
"Module32First" );
pModule32Next = ( MODULEWALK ) GetProcAddress( hKernel,
"Module32Next" );
pProcess32First = ( PROCESSWALK ) GetProcAddress( hKernel,
"Process32First" );
pProcess32Next = ( PROCESSWALK ) GetProcAddress( hKernel,
"Process32Next" );
pThread32First = ( THREADWALK ) GetProcAddress( hKernel,
"Thread32First" );
pThread32Next = ( THREADWALK ) GetProcAddress( hKernel,
"Thread32Next" );
pHeap32ListFirst = ( HEAPLISTWALK ) GetProcAddress( hKernel,
"Heap32ListFirst" );
pHeap32ListNext = ( HEAPLISTWALK ) GetProcAddress( hKernel,
"Heap32ListNext" );
pHeap32First = ( HEAPFIRST ) GetProcAddress( hKernel,
"Heap32First" );
pHeap32Next = ( HEAPNEXT ) GetProcAddress( hKernel,
"Heap32Next" );
/* 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;
status = initRandomData( randomState, buffer, BIG_RANDOM_BUFSIZE );
if( cryptStatusError( status ) )
retIntError_Void();
/* Take a snapshot of everything we can get to that's currently in the
system */
hSnapshot = pCreateToolhelp32Snapshot( TH32CS_SNAPALL, 0 );
if( !hSnapshot )
return;
/* 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 Win95/98, since it implies a large/long-running
server app that would be run under NT/Win2K/et al rather than
Win95 (the performance of the mapped ToolHelp32 helper functions
under these OSes is even worse than under Win95, fortunately we
don't have to use them there).
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 */
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() )
{
CloseHandle( 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( &he32, hl32.th32ProcessID, hl32.th32HeapID ) )
{
do
{
if( krnlIsExiting() )
{
CloseHandle( hSnapshot );
return;
}
addRandomData( randomState, &he32,
sizeof( HEAPENTRY32 ) );
}
while( entryCount++ < 20 && pHeap32Next( &he32 ) );
}
}
while( listCount++ < 20 && pHeap32ListNext( hSnapshot, &hl32 ) );
}
/* Walk through all processes */
pe32.dwSize = sizeof( PROCESSENTRY32 );
iterationCount = 0;
if( pProcess32First( hSnapshot, &pe32 ) )
{
do
{
if( krnlIsExiting() )
{
CloseHandle( hSnapshot );
return;
}
addRandomData( randomState, &pe32, sizeof( PROCESSENTRY32 ) );
}
while( pProcess32Next( hSnapshot, &pe32 ) && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
}
/* Walk through all threads */
te32.dwSize = sizeof( THREADENTRY32 );
iterationCount = 0;
if( pThread32First( hSnapshot, &te32 ) )
{
do
{
if( krnlIsExiting() )
{
CloseHandle( hSnapshot );
return;
}
addRandomData( randomState, &te32, sizeof( THREADENTRY32 ) );
}
while( pThread32Next( hSnapshot, &te32 ) && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
}
/* Walk through all modules associated with the process */
me32.dwSize = sizeof( MODULEENTRY32 );
iterationCount = 0;
if( pModule32First( hSnapshot, &me32 ) )
{
do
{
if( krnlIsExiting() )
{
CloseHandle( hSnapshot );
return;
}
addRandomData( randomState, &me32, sizeof( MODULEENTRY32 ) );
}
while( pModule32Next( hSnapshot, &me32 ) && \
iterationCount++ < FAILSAFE_ITERATIONS_LARGE );
}
/* Clean up the snapshot */
CloseHandle( hSnapshot );
if( krnlIsExiting() )
return;
/* Flush any remaining data through */
endRandomData( randomState, 100 );
}
/* Perform a thread-safe slow poll for Windows 95 */
unsigned __stdcall threadSafeSlowPollWin95( void *dummy )
{
UNUSED_ARG( dummy );
slowPollWin95();
_endthreadex( 0 );
return( 0 );
}
/* Type definitions for function pointers to call NetAPI32 functions */
typedef DWORD ( WINAPI *NETSTATISTICSGET )( LPWSTR szServer, LPWSTR szService,
DWORD dwLevel, DWORD dwOptions,
LPBYTE *lpBuffer );
typedef DWORD ( WINAPI *NETAPIBUFFERSIZE )( LPVOID lpBuffer, LPDWORD cbBuffer );
typedef DWORD ( WINAPI *NETAPIBUFFERFREE )( LPVOID lpBuffer );
/* Type definitions for functions to call native NT functions */
typedef DWORD ( WINAPI *NTQUERYSYSTEMINFORMATION )( DWORD systemInformationClass,
PVOID systemInformation,
ULONG systemInformationLength,
PULONG returnLength );
typedef DWORD ( WINAPI *NTQUERYINFORMATIONPROCESS )( HANDLE processHandle,
DWORD processInformationClass,
PVOID processInformation,
ULONG processInformationLength,
PULONG returnLength );
typedef DWORD ( WINAPI *NTPOWERINFORMATION )( DWORD powerInformationClass,
PVOID inputBuffer, ULONG inputBufferLength,
PVOID outputBuffer, ULONG outputBufferLength );
/* Global function pointers. These are necessary because the functions need to
be dynamically linked since only the WinNT kernel currently contains them.
Explicitly linking to them will make the program unloadable under Win95 */
static NETSTATISTICSGET pNetStatisticsGet = NULL;
static NETAPIBUFFERSIZE pNetApiBufferSize = NULL;
static NETAPIBUFFERFREE pNetApiBufferFree = NULL;
static NTQUERYSYSTEMINFORMATION pNtQuerySystemInformation = NULL;
static NTQUERYINFORMATIONPROCESS pNtQueryInformationProcess = NULL;
static NTPOWERINFORMATION pNtPowerInformation = NULL;
/* When we query the performance counters, we allocate an initial buffer and
then reallocate it as required until RegQueryValueEx() stops returning
ERROR_MORE_DATA. The following values define the initial buffer size and
step size by which the buffer is increased */
#define PERFORMANCE_BUFFER_SIZE 65536 /* Start at 64K */
#define PERFORMANCE_BUFFER_STEP 16384 /* Step by 16K */
static void registryPoll( void )
{
static int cbPerfData = PERFORMANCE_BUFFER_SIZE;
PPERF_DATA_BLOCK pPerfData;
MESSAGE_DATA msgData;
DWORD dwSize, dwStatus;
int iterations = 0, status;
/* Wait for any async keyset driver binding to complete. You may be
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -