/** * @brief: 进入下一个阶段 * * @param phase 阶段ID * @param interval_usec 超时时间 * @param waiting_cmd 进入的阶段要等待的CMD */ void TransactionBase::EnterPhase(unsigned int phase, TransactionWaitInterval interval_usec, unsigned int waiting_cmd) { FUNC_TRACE(uin_); SetPhase(phase); SetTimeoutTimer(interval_usec); SetCurrCmd(waiting_cmd); }
VOID WINAPI ServiceHandler( DWORD dwControl ) { const char *pszCommand = SERVICE_CONTROL_STRING_EMPTY; DWORD dwState = gdwState; BOOL fUseTimer = FALSE; #ifdef _DEBUG TCHAR szBuffer[ 256 ]; #endif // _DEBUG ALERT( "ServiceHandler: Incoming service control message..." ); switch( dwControl ) { case SERVICE_CONTROL_START: pszCommand = SERVICE_CONTROL_STRING_START; // This control message requires that we change the state... dwState = SERVICE_START_PENDING; fUseTimer = TRUE; gdwTimeoutState = SERVICE_RUNNING; break; case SERVICE_CONTROL_STOP: pszCommand = SERVICE_CONTROL_STRING_STOP; // This control message requires that we change the state... dwState = SERVICE_STOP_PENDING; fUseTimer = TRUE; gdwTimeoutState = SERVICE_STOPPED; break; case SERVICE_CONTROL_PAUSE: pszCommand = SERVICE_CONTROL_STRING_PAUSE; // This control message requires that we change the state... // ...but if we are already paused then don't if( SERVICE_PAUSED != gdwState ) { dwState = SERVICE_PAUSE_PENDING; } fUseTimer = TRUE; gdwTimeoutState = SERVICE_PAUSED; break; case SERVICE_CONTROL_CONTINUE: pszCommand = SERVICE_CONTROL_STRING_CONTINUE; // This control message requires that we change the state... // ...but only if we are already paused. if( SERVICE_PAUSED == gdwState ) { dwState = SERVICE_CONTINUE_PENDING; } fUseTimer = TRUE; gdwTimeoutState = SERVICE_RUNNING; break; case SERVICE_CONTROL_SHUTDOWN: pszCommand = SERVICE_CONTROL_STRING_SHUTDOWN; // No dwState value for this control message // No gdwTimeoutState for this state break; /////////////////////////////////////////////////////////////// // Start nonstates (these are commands) // Fix by Thomas Kratz [[email protected]] // Control command messages have not associated state // so don't set the dwState case SERVICE_CONTROL_INTERROGATE: pszCommand = SERVICE_CONTROL_STRING_INTERROGATE; gdwLastControlMessage = dwControl; // No dwState value for this control message // No gdwTimoutState for this state break; // Win2k control codes... case SERVICE_CONTROL_PARAMCHANGE: pszCommand = SERVICE_CONTROL_STRING_PARAMCHANGE; // No dwState value for this control message break; case SERVICE_CONTROL_NETBINDADD: pszCommand = SERVICE_CONTROL_STRING_NETBINDADD; // No dwState value for this control message break; case SERVICE_CONTROL_NETBINDREMOVE: pszCommand = SERVICE_CONTROL_STRING_NETBINDREMOVE; // No dwState value for this control message break; case SERVICE_CONTROL_NETBINDENABLE: pszCommand = SERVICE_CONTROL_STRING_NETBINDENABLE; // No dwState value for this control message break; case SERVICE_CONTROL_NETBINDDISABLE: pszCommand = SERVICE_CONTROL_STRING_NETBINDDISABLE; // No dwState value for this control message break; #ifdef SERVICE_CONTROL_PRESHUTDOWN case SERVICE_CONTROL_PRESHUTDOWN : pszCommand = SERVICE_CONTROL_STRING_PRESHUTDOWN ; // No dwState value for this control message break; #endif // User defined control codes...there are 128 of them case SERVICE_CONTROL_USER_DEFINED: case SERVICE_CONTROL_USER_DEFINED + 0x01: case SERVICE_CONTROL_USER_DEFINED + 0x4f: // No dwState value for this control message break; default: pszCommand = SERVICE_CONTROL_STRING_DEFAULT; // No dwState value for this control message break; } // Set the last control message to what was received. Some control messages // result in a state change but we should always report the message. gdwLastControlMessage = dwControl; #ifdef _DEBUG wsprintf( szBuffer, "ServiceHandler: Received message => %s (0x%0x)\n", pszCommand, dwControl ); ALERT( szBuffer ); #endif // _DEBUG // TODO: // We should set an alarm to for some configurable timeout value so that // in case the perl script does not process the request we will change // the state automatically if( FALSE != fUseTimer ) { SetTimeoutTimer( gdwHandlerTimeout ); } // // Update the service status with the dwState. If there were // control messages that warrant a state change then do it // otherwise dwState was set (at beginning of this function) // to be the same as the current state. // UpdateServiceStatus( dwState ); // // This code is only used when in callback mode... // Post a daemon state change message to the main Win32::Daemon // thread so that it knows to callback into Perl. // if( FALSE != gfCallbackMode ) { ALERT( "ServiceHandler: Posting message to main thread for callbacks\n" ); // // Post to the main thread that we have a state change. // // Make sure to post the dwControl value (not dwState). This control value // maps directly to callback index values! // PostThreadMessage( gMainThreadId, WM_DAEMON_STATE_CHANGE, (WORD) dwControl, 0 ); } }
////////////////////////////////////////////////////////////////////////////////////////////////////////////////// // ServiceMain() // Called by the Service Manager. VOID WINAPI ServiceMain( DWORD dwArgs, LPTSTR *ppszArgs) { HWND hWnd = NULL; LPCTSTR pszServiceName = ppszArgs[0]; // // Record this ServiceMain's thread ID for other threads to use. // gServiceMainThreadID = GetCurrentThreadId(); ALERT( "ServiceMain: function started. Passed inn Name is...\n" ); ALERT( pszServiceName ); ALERT( "ServiceMain: About to call RegisterServiceCtrlHandler()...\n" ); // Test to see if we can cause the message loop to start queuing... SetTimeoutTimer( 10 ); CleanStatusStruct( &gServiceStatus ); gServiceStatus.dwCurrentState = SERVICE_START_PENDING; ghService = RegisterServiceCtrlHandler( pszServiceName, ServiceHandler ); if( 0 != ghService ) { ALERT( "ServiceMain: Just came out of RegisterServiceCtrlHandler()" ); // If the state has not yet changed then push start everything... if( 0 == gdwState ) { gdwState = SERVICE_START_PENDING; // // If we are in callback mode then make sure to // start by posting a SERVICE_START_PENDING message // (even though one does not exist in the Win32 API) // so the script has a chance to start. // if( FALSE != gfCallbackMode ) { // // Call the service handler indicating that the "fake" // SERVICE_CONTROL_START event has been received. // ServiceHandler( SERVICE_CONTROL_START ); } } { char szBuffer[256]; sprintf( szBuffer, "ServiceMain: About to call My_SetServiceBits with gdwServiceBits=0x%08x", gdwServiceBits ); ALERT( szBuffer ); } if( 0 != gdwServiceBits ) { My_SetServiceBits( ghService, gdwServiceBits, TRUE, TRUE ); } ALERT( "ServiceMain: Entering message loop" ); // Call a Win32 User level function to create a message queue GetDesktopWindow(); GetWindow( NULL, GW_HWNDFIRST ); if( 1 ) { MSG Message; BOOL fContinueProcessing = TRUE; while( TRUE == fContinueProcessing ) { ALERT( "ServiceMain: Just enetered the message loop" ); try { fContinueProcessing = (BOOL) GetMessage( &Message, (HWND) NULL, 0, 0 ); #ifdef _DEBUG TCHAR szBuffer[256]; wsprintf( szBuffer, "Got message: 0x%08x", Message.message ); ALERT( szBuffer ); #endif // _DEBUG } catch (...) { ALERT( "ServiceMain: Ouch!!! We caught an exception!" ); } switch( Message.message ) { case WM_USER_SET_TIMER: ALERT( "ServiceMain: Setting timer" ); ghTimer = ::SetTimer( NULL, SERVICE_THREAD_TIMER_ID, (UINT)Message.wParam * DEFAULT_HANDLER_TIMEOUT_SCALE, (TIMERPROC)TimerHandler ); break; case WM_QUIT: fContinueProcessing = FALSE; break; case WM_QUERYENDSESSION: case WM_ENDSESSION: case WM_TIMER: ALERT( "ServiceMain: HandlerTimeoutTimer due to WM_TIMER." ); KillTimer(); gdwState = gdwTimeoutState; UpdateServiceStatus( gdwTimeoutState ); default: ALERT( "ServiceMain: Dispatching message." ); TranslateMessage( &Message ); // // Calling DispatchMessage() is probably foolish since // there is no window associated with this thread. // Per MSDN: messages that are not associated with a window cannot be dispatched by the DispatchMessage function DispatchMessage( &Message ); } } } ALERT( "ServiceMain: Just left the message loop." ); UpdateServiceStatus( gdwState ); } else { gdwState = SERVICE_STOPPED; #ifdef _DEBUG TCHAR szBuffer[ 100 ]; wsprintf( szBuffer, TEXT( "ServiceMain: ERROR! 0x08x" ), GetLastError() ); ALERT( szBuffer ); #endif // _DEBUG } ALERT( "ServiceMain: Shutting down ServiceMain()!" ); return; }