EVQ_API int evq_wait (struct event_queue *evq, msec_t timeout) { struct event *ev_ready = NULL; struct win32thr *wth = &evq->head; struct win32thr *threads = wth->next; CRITICAL_SECTION *head_cs = &wth->cs; HANDLE head_signal = wth->signal; int n = wth->n; int sig_ready = 0; DWORD wait_res; if (threads && win32thr_poll(evq) && evq_is_empty(evq)) return 0; if (timeout != 0L) { timeout = timeout_get(wth->tq, timeout, evq->now); if (timeout == 0L) { ev_ready = timeout_process(wth->tq, NULL, evq->now); goto end; } } if (is_WinNT) { if (!iocp_is_empty(evq)) ev_ready = win32iocp_process(evq, NULL, 0L); if (ev_ready) { evq->ev_ready = ev_ready; timeout = 0L; } else { /* head_signal is resetted by IOCP WSARecv/WSASend */ EnterCriticalSection(head_cs); if (evq->sig_ready) timeout = 0L; LeaveCriticalSection(head_cs); } } sys_vm_leave(); wait_res = MsgWaitForMultipleObjects(n + 1, wth->handles, FALSE, timeout, (evq->win_msg ? QS_ALLEVENTS : 0)); sys_vm_enter(); evq->now = sys_milliseconds(); ev_ready = evq->ev_ready; if (wait_res == WAIT_TIMEOUT) { if (ev_ready) goto end; if (!wth->tq && !evq->sig_ready) return EVQ_TIMEOUT; } if (wait_res == (DWORD) (WAIT_OBJECT_0 + n + 1)) { struct event *ev = evq->win_msg; if (ev && !(ev->flags & EVENT_ACTIVE)) { ev->flags |= EVENT_ACTIVE; ev->next_ready = ev_ready; ev_ready = ev; } goto end; } if (wait_res == WAIT_FAILED) return EVQ_FAILED; timeout = evq->now; if (!iocp_is_empty(evq)) ev_ready = win32iocp_process(evq, ev_ready, timeout); wth->idx = wait_res; if (threads) { EnterCriticalSection(head_cs); ResetEvent(head_signal); threads = evq->wth_ready; evq->wth_ready = NULL; sig_ready = evq->sig_ready; evq->sig_ready = 0; LeaveCriticalSection(head_cs); if (wait_res == (DWORD) (WAIT_OBJECT_0 + n)) wth = threads; else wth->next_ready = threads; } else { wth->next_ready = NULL; if (evq->sig_ready) { EnterCriticalSection(head_cs); ResetEvent(head_signal); sig_ready = evq->sig_ready; evq->sig_ready = 0; LeaveCriticalSection(head_cs); } } if (sig_ready) ev_ready = signal_process_interrupt(evq, sig_ready, ev_ready, timeout); for (; wth; wth = wth->next_ready) { HANDLE *hp; /* event handles */ const int idx = wth->idx; int i; wth->state = WTHR_SLEEP; if (wth->tq) { if (idx == WAIT_TIMEOUT) { ev_ready = timeout_process(wth->tq, ev_ready, timeout); continue; } } hp = &wth->handles[idx]; n = wth->n; i = idx; if (i >= n) continue; /* some events deleted? */ /* Traverse array of events */ for (; ; ) { WSANETWORKEVENTS ne; struct event *ev = wth->events[i]; const int ev_flags = ev->flags; unsigned int res = 0; if (!(ev_flags & EVENT_SOCKET)) { if (ev_flags & EVENT_PID) { DWORD status; GetExitCodeProcess(ev->fd, &status); res = (status << EVENT_EOF_SHIFT_RES); } else ResetEvent(ev->fd); /* all events must be manual-reset */ res |= EVENT_READ_RES; } else if (!WSAEnumNetworkEvents((int) ev->fd, *hp, &ne)) { if ((ev_flags & EVENT_READ) && (ne.lNetworkEvents & WFD_READ)) res = EVENT_READ_RES; if ((ev_flags & EVENT_WRITE) && (ne.lNetworkEvents & WFD_WRITE)) res |= EVENT_WRITE_RES; if (ne.lNetworkEvents & FD_CLOSE) res |= EVENT_EOF_RES; } if (res) { ev->flags |= EVENT_ACTIVE | res; ev->next_ready = ev_ready; ev_ready = ev; if (ev_flags & EVENT_ONESHOT) { win32thr_del(wth, ev); --i, --n, --hp; } else if (ev->tq && !(ev_flags & EVENT_TIMEOUT_MANUAL)) timeout_reset(ev, timeout); } /* skip inactive events */ do { if (++i == n) goto end_thread; } while (WaitForSingleObject(*(++hp), 0) != WAIT_OBJECT_0); } end_thread: ((void) 0); /* avoid warning */ } /* always check window messages */ { struct event *ev = evq->win_msg; if (ev && GetQueueStatus(QS_ALLEVENTS)) { ev->next_ready = ev_ready; ev_ready = ev; } } if (!ev_ready) return (wait_res == WAIT_TIMEOUT && !sig_ready) ? EVQ_TIMEOUT : 0; end: evq->ev_ready = ev_ready; return 0; }
void fastPoll( void ) { static BOOLEAN addedFixedItems = FALSE, hasHardwareRNG = FALSE; static CEGENRANDOM pCeGenRandom = NULL; static GETSYSTEMPOWERSTATUS pGetSystemPowerStatusEx2 = NULL; FILETIME creationTime, exitTime, kernelTime, userTime; LARGE_INTEGER performanceCount; SYSTEM_POWER_STATUS_EX2 powerStatus; MEMORYSTATUS memoryStatus; HANDLE handle; POINT point; RANDOM_STATE randomState; BYTE buffer[ RANDOM_BUFSIZE ]; int length; if( krnlIsExiting() ) return; /* Initialize the native function pointers if necessary. CeGetRandom() is only available in relatively new versions of WinCE, so we have to link it dynamically */ if( pCeGenRandom == NULL ) { HANDLE hCoreDLL; if( ( hCoreDLL = GetModuleHandle( TEXT( "Coredll.dll" ) ) ) != NULL ) pCeGenRandom = ( CEGENRANDOM ) GetProcAddress( hCoreDLL, TEXT( "CeGenRandom" ) ); } if( pGetSystemPowerStatusEx2 == NULL ) { HANDLE hGetpower; if( ( hGetpower = GetModuleHandle( TEXT( "Getpower.dll" ) ) ) != NULL ) pGetSystemPowerStatusEx2 = ( GETSYSTEMPOWERSTATUS ) \ GetProcAddress( hGetpower, TEXT( "GetSystemPowerStatusEx2" ) ); } initRandomData( randomState, buffer, RANDOM_BUFSIZE ); /* Get various basic pieces of system information: Handle of active window, handle of window with mouse capture, handle of clipboard owner handle of start of clpboard viewer list, pseudohandle of current process, current process ID, pseudohandle of current thread, current thread ID, handle of desktop window, handle of window with keyboard focus, whether system queue has any events, cursor position for last message, 1 ms time for last message, handle of window with clipboard open, handle of process heap, handle of procs window station, types of events in input queue, and milliseconds since Windows was started */ addRandomValue( randomState, GetActiveWindow() ); addRandomValue( randomState, GetCapture() ); addRandomValue( randomState, GetCaretBlinkTime() ); addRandomValue( randomState, GetClipboardOwner() ); addRandomValue( randomState, GetCurrentProcess() ); addRandomValue( randomState, GetCurrentProcessId() ); addRandomValue( randomState, GetCurrentThread() ); addRandomValue( randomState, GetCurrentThreadId() ); addRandomValue( randomState, GetDesktopWindow() ); addRandomValue( randomState, GetDC( NULL ) ); addRandomValue( randomState, GetDoubleClickTime() ); addRandomValue( randomState, GetFocus() ); addRandomValue( randomState, GetForegroundWindow() ); addRandomValue( randomState, GetMessagePos() ); addRandomValue( randomState, GetOpenClipboardWindow() ); addRandomValue( randomState, GetProcessHeap() ); addRandomValue( randomState, GetQueueStatus( QS_ALLINPUT ) ); addRandomValue( randomState, GetTickCount() ); if( krnlIsExiting() ) return; /* Get multiword system information: Current caret position, current mouse cursor position */ GetCaretPos( &point ); addRandomData( randomState, &point, sizeof( POINT ) ); GetCursorPos( &point ); addRandomData( randomState, &point, sizeof( POINT ) ); /* Get percent of memory in use, bytes of physical memory, bytes of free physical memory, bytes in paging file, free bytes in paging file, user bytes of address space, and free user bytes */ memoryStatus.dwLength = sizeof( MEMORYSTATUS ); GlobalMemoryStatus( &memoryStatus ); addRandomData( randomState, &memoryStatus, sizeof( MEMORYSTATUS ) ); /* Get thread and process creation time, exit time, time in kernel mode, and time in user mode in 100ns intervals */ handle = GetCurrentThread(); GetThreadTimes( handle, &creationTime, &exitTime, &kernelTime, &userTime ); addRandomData( randomState, &creationTime, sizeof( FILETIME ) ); addRandomData( randomState, &exitTime, sizeof( FILETIME ) ); addRandomData( randomState, &kernelTime, sizeof( FILETIME ) ); addRandomData( randomState, &userTime, sizeof( FILETIME ) ); /* Get extended battery/power status information. We set the fUpdate flag to force a re-read of fresh data rather than a re-use of cached information */ if( pGetSystemPowerStatusEx2 != NULL && \ ( length = \ pGetSystemPowerStatusEx2( &powerStatus, sizeof( SYSTEM_POWER_STATUS_EX2 ), TRUE ) ) > 0 ) addRandomData( randomState, &powerStatus, length ); /* Get random data provided by the OS. Since this is expected to be provided by the system vendor, it's quite likely to be the usual process ID + time */ if( pCeGenRandom != NULL ) { BYTE randomBuffer[ 32 ]; if( pCeGenRandom( 32, randomBuffer ) ) addRandomData( randomState, randomBuffer, 32 ); } /* The following are fixed for the lifetime of the process so we only add them once */ if( !addedFixedItems ) { SYSTEM_INFO systemInfo; GetSystemInfo( &systemInfo ); addRandomData( randomState, &systemInfo, sizeof( SYSTEM_INFO ) ); addedFixedItems = TRUE; } /* The performance of QPC varies depending on the architecture it's running on, and is completely platform-dependant. If there's no hardware performance counter available, it uses the 1ms system timer, although usually there's some form of hardware timer available. Since there may be no correlation, or only a weak correlation, between the performance counter and the system clock, we get the time from both sources */ if( QueryPerformanceCounter( &performanceCount ) ) addRandomData( randomState, &performanceCount, sizeof( LARGE_INTEGER ) ); addRandomValue( randomState, GetTickCount() ); /* Flush any remaining data through. Quality = int( 33 1/3 % ) */ endRandomData( randomState, 34 ); }
int _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, int), int requester ) { static int addedFixedItems = 0; if ( debug_me ) log_debug ("rndw32#gather_random_fast: req=%d\n", requester ); /* Get various basic pieces of system information: Handle of active * window, handle of window with mouse capture, handle of clipboard owner * handle of start of clpboard viewer list, pseudohandle of current * process, current process ID, pseudohandle of current thread, current * thread ID, handle of desktop window, handle of window with keyboard * focus, whether system queue has any events, cursor position for last * message, 1 ms time for last message, handle of window with clipboard * open, handle of process heap, handle of procs window station, types of * events in input queue, and milliseconds since Windows was started */ { byte buffer[20*sizeof(ulong)], *bufptr; bufptr = buffer; #define ADD(f) do { ulong along = (ulong)(f); \ memcpy (bufptr, &along, sizeof (along) ); \ bufptr += sizeof (along); } while (0) ADD ( GetActiveWindow ()); ADD ( GetCapture ()); ADD ( GetClipboardOwner ()); ADD ( GetClipboardViewer ()); ADD ( GetCurrentProcess ()); ADD ( GetCurrentProcessId ()); ADD ( GetCurrentThread ()); ADD ( GetCurrentThreadId ()); ADD ( GetDesktopWindow ()); ADD ( GetFocus ()); ADD ( GetInputState ()); ADD ( GetMessagePos ()); ADD ( GetMessageTime ()); ADD ( GetOpenClipboardWindow ()); ADD ( GetProcessHeap ()); ADD ( GetProcessWindowStation ()); ADD ( GetQueueStatus (QS_ALLEVENTS)); ADD ( GetTickCount ()); assert ( bufptr-buffer < sizeof (buffer) ); (*add) ( buffer, bufptr-buffer, requester ); #undef ADD } /* Get multiword system information: Current caret position, current * mouse cursor position */ { POINT point; GetCaretPos (&point); (*add) ( &point, sizeof (point), requester ); GetCursorPos (&point); (*add) ( &point, sizeof (point), requester ); } /* Get percent of memory in use, bytes of physical memory, bytes of free * physical memory, bytes in paging file, free bytes in paging file, user * bytes of address space, and free user bytes */ { MEMORYSTATUS memoryStatus; memoryStatus.dwLength = sizeof (MEMORYSTATUS); GlobalMemoryStatus (&memoryStatus); (*add) ( &memoryStatus, sizeof (memoryStatus), requester ); } /* Get thread and process creation time, exit time, time in kernel mode, and time in user mode in 100ns intervals */ { HANDLE handle; FILETIME creationTime, exitTime, kernelTime, userTime; DWORD minimumWorkingSetSize, maximumWorkingSetSize; handle = GetCurrentThread (); GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); (*add) ( &creationTime, sizeof (creationTime), requester ); (*add) ( &exitTime, sizeof (exitTime), requester ); (*add) ( &kernelTime, sizeof (kernelTime), requester ); (*add) ( &userTime, sizeof (userTime), requester ); handle = GetCurrentProcess (); GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); (*add) ( &creationTime, sizeof (creationTime), requester ); (*add) ( &exitTime, sizeof (exitTime), requester ); (*add) ( &kernelTime, sizeof (kernelTime), requester ); (*add) ( &userTime, sizeof (userTime), requester ); /* Get the minimum and maximum working set size for the current process */ GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, &maximumWorkingSetSize); (*add) ( &minimumWorkingSetSize, sizeof (minimumWorkingSetSize), requester ); (*add) ( &maximumWorkingSetSize, sizeof (maximumWorkingSetSize), requester ); } /* The following are fixed for the lifetime of the process so we only * add them once */ if (!addedFixedItems) { STARTUPINFO startupInfo; /* Get name of desktop, console window title, new window position and * size, window flags, and handles for stdin, stdout, and stderr */ startupInfo.cb = sizeof (STARTUPINFO); GetStartupInfo (&startupInfo); (*add) ( &startupInfo, sizeof (STARTUPINFO), requester ); addedFixedItems = 1; } /* The performance of QPC varies depending on the architecture it's * running on and on the OS. Under NT it reads the CPU's 64-bit timestamp * counter (at least on a Pentium and newer '486's, it hasn't been tested * on anything without a TSC), under Win95 it reads the 1.193180 MHz PIC * timer. There are vague mumblings in the docs that it may fail if the * appropriate hardware isn't available (possibly '386's or MIPS machines * running NT), but who's going to run NT on a '386? */ { LARGE_INTEGER performanceCount; if (QueryPerformanceCounter (&performanceCount)) { if ( debug_me ) log_debug ("rndw32#gather_random_fast: perf data\n"); (*add) (&performanceCount, sizeof (performanceCount), requester); } else { /* Millisecond accuracy at best... */ DWORD aword = GetTickCount (); (*add) (&aword, sizeof (aword), requester ); } } return 0; }
///////////////////////////////////////////////////////////////////////// // The thread process the user's conversation: Get user's request command, send it // to scheduler, Get the response code and return it to user. // The parameter "lpvParam" if the NamedPipe instance handle value. DWORD WINAPI TcpipClientAgentThread( LPVOID lpvParam ) { LPTS_COM_PROPS lptsComProps; REQUEST Request; CHAR szBuffer[PIPE_BUFFER_SIZE]; DWORD cbWriten, cbReaded; DWORD dwRetCode; int iRet; BOOL fDirect = TRUE; MSG Msg; SOCKET iSocket; iSocket = (SOCKET)lpvParam; // If the parameter lpvParam is an invalid pipe handle. //if( iSocket == SOCKET_ERROR ) // ExitThread( ERROR_INVALID_PARAMETER ); GetQueueStatus( QS_SENDMESSAGE ); lprintfs( "Client agent thread starts.\n" ); _try { // Wait and read the message send by the client, until the client post. cbReaded = recvPacket(iSocket, szBuffer, PIPE_BUFFER_SIZE); //if( cbReaded == SOCKET_ERROR ) { if( cbReaded <= 0 ) { ExitThread( GetLastError() ); } // Get the packet header, analyse the packet information. lptsComProps = (LPTS_COM_PROPS)szBuffer; // If the user's first packet is not logon information packet, // Reject the user's request. if( lptsComProps->packetType != pkTS_SYNC_PIPE || lptsComProps->msgType != msgTS_CLIENT_LOGON ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_ERROR; lptsComProps->msgType = msgTS_ERROR_MSG; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "User can not access the server before logon." ); iRet = sendPacket(iSocket, szBuffer, lptsComProps->len+sizeof( TS_COM_PROPS ) ); //if( iRet == SOCKET_ERROR ) { if( iRet <= 0 ) { ExitThread( GetLastError() ); } ExitThread( TERR_NOT_LOGON ); } #ifndef TREESVR_STANDALONE // Add by Jingyu Niu, 2000.08.25, for support single user mode. if( singleUserMode ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = 0x10000; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "Server now running in single user mode, not accept connect request." ); cbWriten = sendPacket( iSocket, szBuffer, lptsComProps->len+sizeof(TS_COM_PROPS) ); //if( cbWriten == SOCKET_ERROR ) { if( cbWriten <= 0 ) { ExitThread( GetLastError() ); } ExitThread( 0x10000 ); } #endif // If the user's logon information packet is invalid, // Reject the user's request. dwRetCode = MsgToRequest( (LPCSTR)(szBuffer+sizeof( TS_COM_PROPS )), &Request ); if( dwRetCode != TERR_SUCCESS ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = dwRetCode; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "Logon information error(error code:%ld).", dwRetCode ); cbWriten = sendPacket( iSocket, szBuffer, lptsComProps->len+sizeof(TS_COM_PROPS) ); //if( cbWriten == SOCKET_ERROR ) { if( cbWriten <= 0 ) { ExitThread( GetLastError() ); } ExitThread( dwRetCode ); } // Send the request to scheduler. dwRetCode = SendRequest( &Request ); if( dwRetCode != TERR_SUCCESS ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_ERROR; lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = dwRetCode; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "Can not logon the server(error code:%ld).", dwRetCode ); cbWriten = sendPacket( iSocket, szBuffer, lptsComProps->len+sizeof(TS_COM_PROPS) ); //if( cbWriten == SOCKET_ERROR ) { if( cbWriten <= 0 ) { ExitThread( GetLastError() ); } ExitThread( dwRetCode ); } ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_SYNC_PIPE; if( Request.dwRequest == TERR_SUCCESS ) { lptsComProps->msgType = msgTS_LOGON_OK; lptsComProps->lp = Request.dwRequestId; } else { lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = Request.dwRequest; } cbWriten = sendPacket( iSocket, szBuffer, sizeof(TS_COM_PROPS) ); //if( cbWriten == SOCKET_ERROR ) { if( cbWriten <= 0 ) { ExitThread( GetLastError() ); } if( Request.dwRequest != TERR_SUCCESS ) { ExitThread( TERR_SUCCESS ); } // Add by NiuJingyu, 1998.03 GetMessage( &Msg, NULL, TS_SERVICE_START, TS_SERVICE_START ); dwRetCode = TERR_SUCCESS; while( 1 ) { if( fDirect ) { cbReaded = recvPacket(iSocket, szBuffer, PIPE_BUFFER_SIZE); //if( cbReaded == SOCKET_ERROR ) { if( cbReaded <= 0 ) { dwRetCode = GetLastError(); CliSetExchBufError( Request.lpExchangeBuf ); dwRetCode = TERR_CLIENT_CLOSE; break; } lptsComProps = (LPTS_COM_PROPS)szBuffer; if( lptsComProps->endPacket == '\x0' ) fDirect = FALSE; if( lptsComProps->packetType == pkTS_SYNC_PIPE ) { if( lptsComProps->msgType == msgTS_PIPE_CLOSE ) { dwRetCode = TERR_SUCCESS; break; } } #ifndef TREESVR_STANDALONE // Add by Jingyu Niu, 2000.08.25, for support single user mode. if( singleUserMode && singleUserThread != GetCurrentThreadId() ) { if( fDirect ) continue; else { dwRetCode = TERR_SUCCESS; break; } } #endif // lprintfs( "########################## Client write exchange buffer.\n" ); dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); if( dwRetCode != TERR_SUCCESS ) { break; } } else { // Service thread is voluntary. // Read the packet from service thread. dwRetCode = CliReadExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); if( dwRetCode != TERR_SUCCESS ) break; lptsComProps = (LPTS_COM_PROPS)szBuffer; if( lptsComProps->endPacket == '\x0' ) fDirect = TRUE; if( lptsComProps->packetType == pkTS_SYNC_PIPE ) { if( lptsComProps->msgType == msgTS_NO_DATA ) continue; } #ifndef TREESVR_STANDALONE // Add by Jingyu Niu, 2000.08.25, for support single user mode. if( singleUserMode && singleUserThread != GetCurrentThreadId() && fDirect ) { lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_PIPE_CLOSE; lptsComProps->lp = 0; lptsComProps->len = 0; lptsComProps->leftPacket = '\x0'; lptsComProps->endPacket = '\x0'; dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); break; } #endif cbWriten = sendPacket( iSocket, szBuffer, lptsComProps->len+sizeof(TS_COM_PROPS) ); //if( cbWriten == SOCKET_ERROR ) { if( cbWriten <= 0 ) { dwRetCode = GetLastError(); CliSetExchBufError( Request.lpExchangeBuf ); break; } } dwRetCode = TERR_SUCCESS; } if( dwRetCode == TERR_SUCCESS ) { ZeroMemory( szBuffer, 4096 ); lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_CLIENT_LOGOFF; dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); if( dwRetCode != TERR_SUCCESS ) CliSetExchBufError( Request.lpExchangeBuf ); } lprintfs( "Client agent thread ends.\n" ); } _except ( EXCEPTION_EXECUTE_HANDLER ) { char szBuffer[256]; wsprintf( szBuffer, "Client adent thread cause an exception.\n" ); MessageBox( NULL, szBuffer, "Inspector", MB_OK | MB_ICONSTOP ); } closesocket( iSocket ); ExitThread( TERR_SUCCESS ); return 0; }
// The thread process the user's conversation: Get user's request command, send it // to scheduler, Get the response code and return it to user. // The parameter "lpvParam" if the NamedPipe instance handle value. DWORD WINAPI ClientAgentThread ( LPVOID lpvParam ) { LPTS_COM_PROPS lptsComProps; REQUEST Request; CHAR szBuffer[PIPE_BUFFER_SIZE]; DWORD cbWriten, cbReaded; DWORD dwRetCode; BOOL fSuccess; BOOL fDirect = TRUE; MSG Msg; #ifdef TREESVR_STANDALONE HANDLE hReadPipe, hWritePipe; hReadPipe = ( ( PIPE_STRU * )lpvParam )->hReadPipe; hWritePipe = ( ( PIPE_STRU * )lpvParam )->hWritePipe; #else HANDLE hPipe; hPipe = (HANDLE) lpvParam; // If the parameter lpvParam is an invalid pipe handle. if( hPipe == 0 || hPipe == INVALID_HANDLE_VALUE ) ExitThread( ERROR_INVALID_PARAMETER ); #endif GetQueueStatus( QS_SENDMESSAGE ); lprintfs( "Client agent thread starts.\n" ); _try { // Wait and read the message send by the client, until the client post. #ifdef TREESVR_STANDALONE fSuccess = ReadFile ( hReadPipe, szBuffer, PIPE_BUFFER_SIZE, &cbReaded, NULL ); #else fSuccess = ReadFile ( hPipe, szBuffer, PIPE_BUFFER_SIZE, &cbReaded, NULL ); #endif if( !fSuccess ) { #ifdef TREESVR_STANDALONE // FlushFileBuffers( hWritePipe ); #else FlushFileBuffers( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle( hPipe ); #endif ExitThread( GetLastError() ); } // Get the packet header, analyse the packet information. lptsComProps = (LPTS_COM_PROPS)szBuffer; // If the user's first packet is not logon information packet, // Reject the user's request. if( lptsComProps->packetType != pkTS_SYNC_PIPE || lptsComProps->msgType != msgTS_CLIENT_LOGON ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_ERROR; lptsComProps->msgType = msgTS_ERROR_MSG; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "User can not access the server before logon." ); #ifdef TREESVR_STANDALONE fSuccess = WriteFile ( hWritePipe, (LPCVOID)szBuffer, // lptsComProps->len+sizeof( TS_COM_PROPS ), PIPE_BUFFER_SIZE, &cbWriten, NULL ); // FlushFileBuffers( hWritePipe ); #else fSuccess = WriteFile ( hPipe, (LPCVOID)szBuffer, lptsComProps->len+sizeof( TS_COM_PROPS ), &cbWriten, NULL ); FlushFileBuffers( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle( hPipe ); #endif ExitThread( TERR_NOT_LOGON ); } #ifndef TREESVR_STANDALONE // Add by Jingyu Niu, 2000.08.25, for support single user mode. if( singleUserMode ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = 0x10000; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "Server now running in single user mode, not accept connect request." ); #ifdef TREESVR_STANDALONE fSuccess = WriteFile ( hWritePipe, (LPCVOID)szBuffer, // lptsComProps->len+sizeof( TS_COM_PROPS ), PIPE_BUFFER_SIZE, &cbWriten, NULL ); // FlushFileBuffers( hWritePipe ); #else fSuccess = WriteFile ( hPipe, (LPCVOID)szBuffer, lptsComProps->len+sizeof( TS_COM_PROPS ), &cbWriten, NULL ); FlushFileBuffers( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle( hPipe ); #endif ExitThread( 0x10000 ); } #endif // If the user's logon information packet is invalid, // Reject the user's request. dwRetCode = MsgToRequest( (LPCSTR)(szBuffer+sizeof( TS_COM_PROPS )), &Request ); if( dwRetCode != TERR_SUCCESS ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = dwRetCode; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "Logon information error(error code:%ld).", dwRetCode ); #ifdef TREESVR_STANDALONE fSuccess = WriteFile ( hWritePipe, (LPCVOID)szBuffer, // lptsComProps->len+sizeof( TS_COM_PROPS ), PIPE_BUFFER_SIZE, &cbWriten, NULL ); // FlushFileBuffers( hWritePipe ); #else fSuccess = WriteFile ( hPipe, (LPCVOID)szBuffer, lptsComProps->len+sizeof( TS_COM_PROPS ), &cbWriten, NULL ); FlushFileBuffers( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle( hPipe ); #endif ExitThread( dwRetCode ); } // Send the request to scheduler. dwRetCode = SendRequest( &Request ); if( dwRetCode != TERR_SUCCESS ) { ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_ERROR; lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = dwRetCode; lptsComProps->len = wsprintfA( (LPSTR)(szBuffer+sizeof( TS_COM_PROPS )), "Can not logon the server(error code:%ld).", dwRetCode ); #ifdef TREESVR_STANDALONE fSuccess = WriteFile ( hWritePipe, (LPCVOID)szBuffer, // lptsComProps->len+sizeof( TS_COM_PROPS ), PIPE_BUFFER_SIZE, &cbWriten, NULL ); // FlushFileBuffers( hWritePipe ); #else fSuccess = WriteFile ( hPipe, (LPCVOID)szBuffer, lptsComProps->len+sizeof( TS_COM_PROPS ), &cbWriten, NULL ); FlushFileBuffers( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle( hPipe ); #endif ExitThread( dwRetCode ); } ZeroMemory( szBuffer, PIPE_BUFFER_SIZE ); lptsComProps->packetType = pkTS_SYNC_PIPE; if( Request.dwRequest == TERR_SUCCESS ) { lptsComProps->msgType = msgTS_LOGON_OK; lptsComProps->lp = Request.dwRequestId; } else { lptsComProps->msgType = msgTS_LOGON_ERROR; lptsComProps->lp = Request.dwRequest; } #ifdef TREESVR_STANDALONE fSuccess = WriteFile ( hWritePipe, (LPCVOID)szBuffer, // sizeof( TS_COM_PROPS ), PIPE_BUFFER_SIZE, &cbWriten, NULL ); #else fSuccess = WriteFile ( hPipe, (LPCVOID)szBuffer, sizeof( TS_COM_PROPS ), &cbWriten, NULL ); #endif if( !fSuccess ) { #ifdef TREESVR_STANDALONE // FlushFileBuffers( hWritePipe ); #else FlushFileBuffers( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle( hPipe ); #endif ExitThread( GetLastError() ); } if( Request.dwRequest != TERR_SUCCESS ) { #ifdef TREESVR_STANDALONE // FlushFileBuffers( hWritePipe ); #else FlushFileBuffers( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle ( hPipe ); #endif ExitThread( TERR_SUCCESS ); } // Add by NiuJingyu, 1998.03 GetMessage( &Msg, NULL, TS_SERVICE_START, TS_SERVICE_START ); dwRetCode = TERR_SUCCESS; // lprintfs( "########################## Begin transfer loop.\n" ); while( 1 ) { if( fDirect ) { // Client is voluntary. // lprintfs( "########################## Read namedpipe.\n" ); #ifdef TREESVR_STANDALONE fSuccess = ReadFile ( hReadPipe, szBuffer, PIPE_BUFFER_SIZE, &cbReaded, NULL ); #else fSuccess = ReadFile ( hPipe, szBuffer, PIPE_BUFFER_SIZE, &cbReaded, NULL ); #endif if( !fSuccess ) { dwRetCode = GetLastError(); if( dwRetCode == ERROR_BROKEN_PIPE ) { //The pipe has been ended. CliSetExchBufError( Request.lpExchangeBuf ); dwRetCode = TERR_CLIENT_CLOSE; break; } } #ifdef TREESVR_STANDALONE // FlushFileBuffers ( hWritePipe ); #else FlushFileBuffers ( hPipe ); #endif lptsComProps = (LPTS_COM_PROPS)szBuffer; if( lptsComProps->endPacket == '\x0' ) fDirect = FALSE; if( lptsComProps->packetType == pkTS_SYNC_PIPE ) { if( lptsComProps->msgType == msgTS_PIPE_CLOSE ) { dwRetCode = TERR_SUCCESS; break; } } #ifndef TREESVR_STANDALONE // Add by Jingyu Niu, 2000.08.25, for support single user mode. if( singleUserMode && singleUserThread != GetCurrentThreadId() ) { if( fDirect ) continue; else { dwRetCode = TERR_SUCCESS; break; } } #endif // lprintfs( "########################## Client write exchange buffer.\n" ); dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); if( dwRetCode != TERR_SUCCESS ) { break; } } else { // Service thread is voluntary. // Read the packet from service thread. dwRetCode = CliReadExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); if( dwRetCode != TERR_SUCCESS ) break; lptsComProps = (LPTS_COM_PROPS)szBuffer; if( lptsComProps->endPacket == '\x0' ) fDirect = TRUE; if( lptsComProps->packetType == pkTS_SYNC_PIPE ) { if( lptsComProps->msgType == msgTS_NO_DATA ) continue; } #ifndef TREESVR_STANDALONE // Add by Jingyu Niu, 2000.08.25, for support single user mode. if( singleUserMode && singleUserThread != GetCurrentThreadId() && fDirect ) { lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_PIPE_CLOSE; lptsComProps->lp = 0; lptsComProps->len = 0; lptsComProps->leftPacket = '\x0'; lptsComProps->endPacket = '\x0'; dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); break; } #endif #ifdef TREESVR_STANDALONE fSuccess = WriteFile ( hWritePipe, (LPCVOID)szBuffer, // lptsComProps->len+sizeof( TS_COM_PROPS ), PIPE_BUFFER_SIZE, &cbWriten, NULL ); #else fSuccess = WriteFile ( hPipe, (LPCVOID)szBuffer, lptsComProps->len+sizeof( TS_COM_PROPS ), &cbWriten, NULL ); #endif if( !fSuccess ) { dwRetCode = GetLastError(); if( dwRetCode == ERROR_NO_DATA ) { // Pipe close in progress. dwRetCode = TERR_CLIENT_CLOSE; CliSetExchBufError( Request.lpExchangeBuf ); break; } } #ifdef TREESVR_STANDALONE // FlushFileBuffers ( hWritePipe ); #else FlushFileBuffers ( hPipe ); #endif } dwRetCode = TERR_SUCCESS; } if( dwRetCode == TERR_SUCCESS ) { ZeroMemory( szBuffer, 4096 ); lptsComProps->packetType = pkTS_SYNC_PIPE; lptsComProps->msgType = msgTS_CLIENT_LOGOFF; dwRetCode = CliWriteExchngBuf( Request.lpExchangeBuf, szBuffer, 4096 ); if( dwRetCode != TERR_SUCCESS ) CliSetExchBufError( Request.lpExchangeBuf ); } lprintfs( "Client agent thread ends.\n" ); #ifdef TREESVR_STANDALONE // FlushFileBuffers ( hWritePipe ); #else FlushFileBuffers ( hPipe ); DisconnectNamedPipe ( hPipe ); CloseHandle ( hPipe ); #endif } _except ( EXCEPTION_EXECUTE_HANDLER ) { char szBuffer[256]; wsprintf( szBuffer, "Client adent thread cause an exception.\n" ); MessageBox( NULL, szBuffer, "Inspector", MB_OK | MB_ICONSTOP ); } ExitThread( TERR_SUCCESS ); return 0; }
/*-------------------------------------------------------*/ PIORB NEAR PreProcessIORBs (NPA npA, NPU npU, PPIORB ppFirstIORB) { PIORB pIORB, pIORBPrev, pIORBNext; USHORT Cmd; #define CmdCode (Cmd >> 8) #define CmdModifier (UCHAR)(Cmd & 0xFF) pIORB = *ppFirstIORB; pIORBPrev = 0; do { pIORBNext = (pIORB->RequestControl & IORB_CHAIN) ? pIORB->pNxtIORB : 0; Cmd = REQ (pIORB->CommandCode, pIORB->CommandModifier); if ((Cmd == REQ (IOCC_ADAPTER_PASSTHRU, IOCM_EXECUTE_CDB)) || (CmdCode == IOCC_CONFIGURATION) || (CmdCode == IOCC_RESOURCE) || (CmdCode == IOCC_DEVICE_CONTROL)) { if (pIORBPrev) { pIORBPrev->pNxtIORB = pIORBNext; } else { *ppFirstIORB = pIORBNext; } if (CmdCode == IOCC_RESOURCE) Cmd = 10 + CmdModifier; if (CmdCode == IOCC_CONFIGURATION) Cmd = 8 + CmdModifier; if (CmdCode == IOCC_ADAPTER_PASSTHRU) { PCHAR SCSICmd = ((PIORB_ADAPTER_PASSTHRU)pIORB)->pControllerCmd; Cmd = 0; if ((SCSICmd[0] == SCSI_START_STOP_UNIT) && (SCSICmd[4] == 2)) Cmd = IOCM_EJECT_MEDIA; } switch (CmdModifier) { case 9 /* IOCM_GET_DEVICE_TABLE */ : GetDeviceTable (pIORB); break; case 10 /* IOCM_COMPLETE_INIT */ : CompleteInit (npA); break; case 11 /* IOCM_REPORT_RESOURCES */ : GetUnitResources (npA, pIORB); break; case IOCM_SUSPEND : SuspendIORBReq (npA, pIORB); break; case IOCM_RESUME : ResumeIORBReq (npA, pIORB); break; case IOCM_GET_QUEUE_STATUS : GetQueueStatus (npA, pIORB); break; case IOCM_EJECT_MEDIA : case IOCM_LOCK_MEDIA : case IOCM_UNLOCK_MEDIA : ProcessLockUnlockEject (npU, pIORB, CmdModifier); break; default: pIORB->Status |= IORB_ERROR; pIORB->ErrorCode = IOERR_CMD_NOT_SUPPORTED; } if (CmdModifier != IOCM_SUSPEND) { pIORB->Status |= IORB_DONE; if (pIORB->RequestControl & IORB_ASYNC_POST) ((PIORBNotify)pIORB->NotifyAddress) (pIORB); } continue; } pIORBPrev = pIORB; } while (pIORB = pIORBNext); if (pIORBPrev) pIORBPrev->pNxtIORB = 0; return (pIORBPrev); }
/* This is the fastpoll function which gathers up info by calling various api's */ BOOL FastPoll (void) { int nOriginalRandIndex = nRandIndex; static BOOL addedFixedItems = FALSE; FILETIME creationTime, exitTime, kernelTime, userTime; DWORD minimumWorkingSetSize, maximumWorkingSetSize; LARGE_INTEGER performanceCount; MEMORYSTATUS memoryStatus; HANDLE handle; POINT point; /* Get various basic pieces of system information */ RandaddInt32 (GetActiveWindow ()); /* Handle of active window */ RandaddInt32 (GetCapture ()); /* Handle of window with mouse capture */ RandaddInt32 (GetClipboardOwner ()); /* Handle of clipboard owner */ RandaddInt32 (GetClipboardViewer ()); /* Handle of start of clpbd.viewer list */ RandaddInt32 (GetCurrentProcess ()); /* Pseudohandle of current process */ RandaddInt32 (GetCurrentProcessId ()); /* Current process ID */ RandaddInt32 (GetCurrentThread ()); /* Pseudohandle of current thread */ RandaddInt32 (GetCurrentThreadId ()); /* Current thread ID */ RandaddInt32 (GetCurrentTime ()); /* Milliseconds since Windows started */ RandaddInt32 (GetDesktopWindow ()); /* Handle of desktop window */ RandaddInt32 (GetFocus ()); /* Handle of window with kb.focus */ RandaddInt32 (GetInputState ()); /* Whether sys.queue has any events */ RandaddInt32 (GetMessagePos ()); /* Cursor pos.for last message */ RandaddInt32 (GetMessageTime ()); /* 1 ms time for last message */ RandaddInt32 (GetOpenClipboardWindow ()); /* Handle of window with clpbd.open */ RandaddInt32 (GetProcessHeap ()); /* Handle of process heap */ RandaddInt32 (GetProcessWindowStation ()); /* Handle of procs window station */ RandaddInt32 (GetQueueStatus (QS_ALLEVENTS)); /* Types of events in input queue */ /* Get multiword system information */ GetCaretPos (&point); /* Current caret position */ RandaddBuf ((unsigned char *) &point, sizeof (POINT)); GetCursorPos (&point); /* Current mouse cursor position */ RandaddBuf ((unsigned char *) &point, sizeof (POINT)); /* Get percent of memory in use, bytes of physical memory, bytes of free physical memory, bytes in paging file, free bytes in paging file, user bytes of address space, and free user bytes */ memoryStatus.dwLength = sizeof (MEMORYSTATUS); GlobalMemoryStatus (&memoryStatus); RandaddBuf ((unsigned char *) &memoryStatus, sizeof (MEMORYSTATUS)); /* Get thread and process creation time, exit time, time in kernel mode, and time in user mode in 100ns intervals */ handle = GetCurrentThread (); GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); handle = GetCurrentProcess (); GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); RandaddBuf ((unsigned char *) &creationTime, sizeof (FILETIME)); RandaddBuf ((unsigned char *) &exitTime, sizeof (FILETIME)); RandaddBuf ((unsigned char *) &kernelTime, sizeof (FILETIME)); RandaddBuf ((unsigned char *) &userTime, sizeof (FILETIME)); /* Get the minimum and maximum working set size for the current process */ GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, &maximumWorkingSetSize); RandaddInt32 (minimumWorkingSetSize); RandaddInt32 (maximumWorkingSetSize); /* The following are fixed for the lifetime of the process so we only add them once */ if (addedFixedItems == 0) { STARTUPINFO startupInfo; /* Get name of desktop, console window title, new window position and size, window flags, and handles for stdin, stdout, and stderr */ startupInfo.cb = sizeof (STARTUPINFO); GetStartupInfo (&startupInfo); RandaddBuf ((unsigned char *) &startupInfo, sizeof (STARTUPINFO)); addedFixedItems = TRUE; } /* The docs say QPC can fail if appropriate hardware is not available. It works on 486 & Pentium boxes, but hasn't been tested for 386 or RISC boxes */ if (QueryPerformanceCounter (&performanceCount)) RandaddBuf ((unsigned char *) &performanceCount, sizeof (LARGE_INTEGER)); else { /* Millisecond accuracy at best... */ DWORD dwTicks = GetTickCount (); RandaddBuf ((unsigned char *) &dwTicks, sizeof (dwTicks)); } // CryptoAPI if (CryptoAPIAvailable && CryptGenRandom (hCryptProv, sizeof (buffer), buffer)) RandaddBuf (buffer, sizeof (buffer)); /* Apply the pool mixing function */ Randmix(); /* Restore the original pool cursor position. If this wasn't done, mouse coordinates could be written to a limited area of the pool, especially when moving the mouse uninterruptedly. The severity of the problem would depend on the length of data written by FastPoll (if it was equal to the size of the pool, mouse coordinates would be written only to a particular 4-byte area, whenever moving the mouse uninterruptedly). */ nRandIndex = nOriginalRandIndex; return TRUE; }
void _gcry_rndw32_gather_random_fast (void (*add)(const void*, size_t, enum random_origins), enum random_origins origin) { static int addedFixedItems = 0; if ( debug_me ) log_debug ("rndw32#gather_random_fast: ori=%d\n", origin ); /* Get various basic pieces of system information: Handle of active window, handle of window with mouse capture, handle of clipboard owner handle of start of clpboard viewer list, pseudohandle of current process, current process ID, pseudohandle of current thread, current thread ID, handle of desktop window, handle of window with keyboard focus, whether system queue has any events, cursor position for last message, 1 ms time for last message, handle of window with clipboard open, handle of process heap, handle of procs window station, types of events in input queue, and milliseconds since Windows was started. */ { byte buffer[20*sizeof(ulong)], *bufptr; bufptr = buffer; #define ADD(f) do { ulong along = (ulong)(f); \ memcpy (bufptr, &along, sizeof (along) ); \ bufptr += sizeof (along); \ } while (0) ADD ( GetActiveWindow ()); ADD ( GetCapture ()); ADD ( GetClipboardOwner ()); ADD ( GetClipboardViewer ()); ADD ( GetCurrentProcess ()); ADD ( GetCurrentProcessId ()); ADD ( GetCurrentThread ()); ADD ( GetCurrentThreadId ()); ADD ( GetDesktopWindow ()); ADD ( GetFocus ()); ADD ( GetInputState ()); ADD ( GetMessagePos ()); ADD ( GetMessageTime ()); ADD ( GetOpenClipboardWindow ()); ADD ( GetProcessHeap ()); ADD ( GetProcessWindowStation ()); ADD ( GetQueueStatus (QS_ALLEVENTS)); ADD ( GetTickCount ()); gcry_assert ( bufptr-buffer < sizeof (buffer) ); (*add) ( buffer, bufptr-buffer, origin ); #undef ADD } /* Get multiword system information: Current caret position, current mouse cursor position. */ { POINT point; GetCaretPos (&point); (*add) ( &point, sizeof (point), origin ); GetCursorPos (&point); (*add) ( &point, sizeof (point), origin ); } /* Get percent of memory in use, bytes of physical memory, bytes of free physical memory, bytes in paging file, free bytes in paging file, user bytes of address space, and free user bytes. */ { MEMORYSTATUS memoryStatus; memoryStatus.dwLength = sizeof (MEMORYSTATUS); GlobalMemoryStatus (&memoryStatus); (*add) ( &memoryStatus, sizeof (memoryStatus), origin ); } /* Get thread and process creation time, exit time, time in kernel mode, and time in user mode in 100ns intervals. */ { HANDLE handle; FILETIME creationTime, exitTime, kernelTime, userTime; DWORD minimumWorkingSetSize, maximumWorkingSetSize; handle = GetCurrentThread (); GetThreadTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); (*add) ( &creationTime, sizeof (creationTime), origin ); (*add) ( &exitTime, sizeof (exitTime), origin ); (*add) ( &kernelTime, sizeof (kernelTime), origin ); (*add) ( &userTime, sizeof (userTime), origin ); handle = GetCurrentProcess (); GetProcessTimes (handle, &creationTime, &exitTime, &kernelTime, &userTime); (*add) ( &creationTime, sizeof (creationTime), origin ); (*add) ( &exitTime, sizeof (exitTime), origin ); (*add) ( &kernelTime, sizeof (kernelTime), origin ); (*add) ( &userTime, sizeof (userTime), origin ); /* Get the minimum and maximum working set size for the current process. */ GetProcessWorkingSetSize (handle, &minimumWorkingSetSize, &maximumWorkingSetSize); (*add) ( &minimumWorkingSetSize, sizeof (minimumWorkingSetSize), origin ); (*add) ( &maximumWorkingSetSize, sizeof (maximumWorkingSetSize), origin ); } /* The following are fixed for the lifetime of the process so we only * add them once */ if (!addedFixedItems) { STARTUPINFO startupInfo; /* Get name of desktop, console window title, new window position and size, window flags, and handles for stdin, stdout, and stderr. */ startupInfo.cb = sizeof (STARTUPINFO); GetStartupInfo (&startupInfo); (*add) ( &startupInfo, sizeof (STARTUPINFO), origin ); addedFixedItems = 1; } /* The performance of QPC varies depending on the architecture it's running on and on the OS, the MS documentation is vague about the details because it varies so much. Under Win9x/ME it reads the 1.193180 MHz PIC timer. Under NT/Win2K/XP it may or may not read the 64-bit TSC depending on the HAL and assorted other circumstances, generally on machines with a uniprocessor HAL KeQueryPerformanceCounter() uses a 3.579545MHz timer and on machines with a multiprocessor or APIC HAL it uses the TSC (the exact time source is controlled by the HalpUse8254 flag in the kernel). That choice of time sources is somewhat peculiar because on a multiprocessor machine it's theoretically possible to get completely different TSC readings depending on which CPU you're currently running on, while for uniprocessor machines it's not a problem. However, the kernel appears to synchronise the TSCs across CPUs at boot time (it resets the TSC as part of its system init), so this shouldn't really be a problem. Under WinCE it's completely platform- dependant, if there's no hardware performance counter available, it uses the 1ms system timer. Another feature of the TSC (although it doesn't really affect us here) is that mobile CPUs will turn off the TSC when they idle, Pentiums will change the rate of the counter when they clock-throttle (to match the current CPU speed), and hyperthreading Pentiums will turn it off when both threads are idle (this more or less makes sense, since the CPU will be in the halted state and not executing any instructions to count). To make things unambiguous, we detect a CPU new enough to call RDTSC directly by checking for CPUID capabilities, and fall back to QPC if this isn't present. */ #ifdef __GNUC__ /* FIXME: We would need to implement the CPU feature tests first. */ /* if (cpu_has_feature_rdtsc) */ /* { */ /* uint32_t lo, hi; */ /* We cannot use "=A", since this would use %rax on x86_64. */ /* __asm__ __volatile__ ("rdtsc" : "=a" (lo), "=d" (hi)); */ /* Ignore high 32 bits, hwich are >1s res. */ /* (*add) (&lo, 4, origin ); */ /* } */ /* else */ #endif /*!__GNUC__*/ { LARGE_INTEGER performanceCount; if (QueryPerformanceCounter (&performanceCount)) { if ( debug_me ) log_debug ("rndw32#gather_random_fast: perf data\n"); (*add) (&performanceCount, sizeof (performanceCount), origin); } else { /* Millisecond accuracy at best... */ DWORD aword = GetTickCount (); (*add) (&aword, sizeof (aword), origin ); } } }
// Waits for the HANDLE hObject. While waiting messages sent // to windows on our thread by SendMessage will be processed. // Using this function to do waits and mutual exclusion // avoids some deadlocks in objects with windows. // Return codes are the same as for WaitForSingleObject DWORD WINAPI WaitDispatchingMessages( HANDLE hObject, DWORD dwWait, HWND hwnd, UINT uMsg, HANDLE hEvent) { BOOL bPeeked = FALSE; DWORD dwResult; DWORD dwStart; DWORD dwThreadPriority; static UINT uMsgId = 0; HANDLE hObjects[2] = { hObject, hEvent }; if (dwWait != INFINITE && dwWait != 0) { dwStart = GetTickCount(); } for (; ; ) { DWORD nCount = NULL != hEvent ? 2 : 1; // Minimize the chance of actually dispatching any messages // by seeing if we can lock immediately. dwResult = WaitForMultipleObjects(nCount, hObjects, FALSE, 0); if (dwResult < WAIT_OBJECT_0 + nCount) { break; } DWORD dwTimeOut = dwWait; if (dwTimeOut > 10) { dwTimeOut = 10; } dwResult = MsgWaitForMultipleObjects( nCount, hObjects, FALSE, dwTimeOut, hwnd == NULL ? QS_SENDMESSAGE : QS_SENDMESSAGE + QS_POSTMESSAGE); if (dwResult == WAIT_OBJECT_0 + nCount || dwResult == WAIT_TIMEOUT && dwTimeOut != dwWait) { MSG msg; if (hwnd != NULL) { while (PeekMessage(&msg, hwnd, uMsg, uMsg, PM_REMOVE)) { DispatchMessage(&msg); } } // Do this anyway - the previous peek doesn't flush out the // messages PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE); if (dwWait != INFINITE && dwWait != 0) { DWORD dwNow = GetTickCount(); // Working with differences handles wrap-around DWORD dwDiff = dwNow - dwStart; if (dwDiff > dwWait) { dwWait = 0; } else { dwWait -= dwDiff; } dwStart = dwNow; } if (!bPeeked) { // Raise our priority to prevent our message queue // building up dwThreadPriority = GetThreadPriority(GetCurrentThread()); if (dwThreadPriority < THREAD_PRIORITY_HIGHEST) { SetThreadPriority(GetCurrentThread(), THREAD_PRIORITY_HIGHEST); } bPeeked = TRUE; } } else { break; } } if (bPeeked) { SetThreadPriority(GetCurrentThread(), dwThreadPriority); if (HIWORD(GetQueueStatus(QS_POSTMESSAGE)) & QS_POSTMESSAGE) { if (uMsgId == 0) { uMsgId = RegisterWindowMessage(TEXT("AMUnblock")); } if (uMsgId != 0) { MSG msg; // Remove old ones while (PeekMessage(&msg, (HWND)-1, uMsgId, uMsgId, PM_REMOVE)) { } } PostThreadMessage(GetCurrentThreadId(), uMsgId, 0, 0); } } return dwResult; }
bool CMSWindowsEventQueueBuffer::isEmpty() const { return (HIWORD(GetQueueStatus(QS_ALLINPUT)) == 0); }