Windows NT 4.0 source code leak
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

758 lines
22 KiB

/*++
Copyright (c) 1992-1996 Microsoft Corporation
Module Name:
snmp.c
Abstract:
Provides service functionality for Proxy Agent.
Environment:
User Mode - Win32
Revision History:
10-May-1996 DonRyan
Removed banner from Technology Dynamics, Inc.
--*/
//--------------------------- WINDOWS DEPENDENCIES --------------------------
//--------------------------- STANDARD DEPENDENCIES -- #include<xxxxx.h> ----
#include <windows.h>
#include <process.h>
#include <stdio.h>
#include <winsvc.h>
//--------------------------- MODULE DEPENDENCIES -- #include"xxxxx.h" ------
#include <snmputil.h>
#include "snmpctrl.h"
#include "..\common\evtlog.h"
//--------------------------- SELF-DEPENDENCY -- ONE #include"module.h" -----
//--------------------------- PUBLIC VARIABLES --(same as in module.h file)--
BOOL noservice;
DWORD platformId;
DWORD WinVersion;
//--------------------------- PRIVATE CONSTANTS -----------------------------
//--------------------------- PRIVATE STRUCTS -------------------------------
//--------------------------- PRIVATE VARIABLES -----------------------------
SERVICE_STATUS_HANDLE hService = 0;
SERVICE_STATUS status =
{SERVICE_WIN32, SERVICE_STOPPED, SERVICE_ACCEPT_STOP, NO_ERROR, 0, 0, 0};
//--------------------------- PRIVATE PROTOTYPES ----------------------------
BOOL agentConfigInit(VOID);
//--------------------------- PRIVATE PROCEDURES ----------------------------
static VOID serviceHandlerFunction(
IN DWORD dwControl)
{
extern HANDLE hExitTrapThreadEvent;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: SVC: serviceHandlerFunction entered, dwControl=%d.\n", dwControl));
// is it a LogLevel change control?
if (SNMP_SERVICE_LOGLEVEL_BASE+SNMP_SERVICE_LOGLEVEL_MIN <= dwControl
&& dwControl <= SNMP_SERVICE_LOGLEVEL_BASE+SNMP_SERVICE_LOGLEVEL_MAX)
{
INT nLogLevel;
nLogLevel = dwControl - SNMP_SERVICE_LOGLEVEL_BASE;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: SVC: loglevel changed to %d.\n", nLogLevel));
SnmpSvcSetLogLevel(nLogLevel);
}
// is it a LogType change control?
else if (SNMP_SERVICE_LOGTYPE_BASE+SNMP_SERVICE_LOGTYPE_MIN <= dwControl
&& dwControl <= SNMP_SERVICE_LOGTYPE_BASE+SNMP_SERVICE_LOGTYPE_MAX)
{
INT nLogType;
nLogType = dwControl - SNMP_SERVICE_LOGTYPE_BASE;
if (!noservice) {
// make sure console based log is prohibited when compiled as service
nLogType &= ~SNMP_OUTPUT_TO_CONSOLE;
}
SNMPDBG((SNMP_LOG_TRACE, "SNMP: SVC: logtype changed to %d.\n", nLogType));
SnmpSvcSetLogType(nLogType);
}
else if (dwControl == SERVICE_CONTROL_STOP)
{
status.dwCurrentState = SERVICE_STOP_PENDING;
status.dwCheckPoint++;
status.dwWaitHint = 20000;
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: SVC: error %d setting service status to pending.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
// set event causing trap thread to terminate, followed by comm thread
if (!SetEvent(hExitTrapThreadEvent))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: SVC: error %s setting termination event.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
status.dwCurrentState = SERVICE_STOPPED;
status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
status.dwServiceSpecificExitCode = 1; // OPENISSUE - svc err code
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: SVC: error %d setting service status to stopped.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
exit(1);
}
}
else
// dwControl == SERVICE_CONTROL_INTERROGATE
// dwControl == SERVICE_CONTROL_PAUSE
// dwControl == SERVICE_CONTROL_CONTINUE
// dwControl == <anything else>
{
if (status.dwCurrentState == SERVICE_STOP_PENDING ||
status.dwCurrentState == SERVICE_START_PENDING)
{
status.dwCheckPoint++;
}
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: SVC: error %d updating service status.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
}
} // end serviceHandlerFunction()
static VOID serviceMainFunction(
IN DWORD dwNumServicesArgs,
IN LPSTR *lpServiceArgVectors)
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: serviceMainFunction entered.\n"));
while(dwNumServicesArgs--)
{
INT nLogLevel;
INT nLogType;
INT temp;
if (1 == sscanf(*lpServiceArgVectors, "/loglevel:%d", &temp))
{
nLogLevel = temp;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: loglevel changed to %d.\n", temp));
SnmpSvcSetLogLevel(nLogLevel);
}
else if (1 == sscanf(*lpServiceArgVectors, "/logtype:%d", &temp))
{
nLogType = temp;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: logtype changed to %d.\n", temp));
SnmpSvcSetLogType(nLogType);
}
else
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: argument %s invalid.\n",
*lpServiceArgVectors));
}
lpServiceArgVectors++;
} // end while()
if (!noservice) {
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: registering service control handler.\n"));
if ((hService = RegisterServiceCtrlHandler("SNMP", serviceHandlerFunction))
== 0)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on RegisterServiceCtrlHander %d\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
status.dwCurrentState = SERVICE_STOPPED;
status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
status.dwServiceSpecificExitCode = 2; // OPENISSUE - svc err code
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d setting servicee status to stopped.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
else
exit(1);
}
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: setting service status to pending.\n"));
status.dwCurrentState = SERVICE_START_PENDING;
status.dwWaitHint = 20000;
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d setting service status to pending.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
}
if (!agentConfigInit())
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on agentConfigInit %d\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
status.dwCurrentState = SERVICE_STOPPED;
status.dwWin32ExitCode = ERROR_SERVICE_SPECIFIC_ERROR;
status.dwServiceSpecificExitCode = 3; // OPENISSUE - svc err code
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d setting service status to stopped.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
exit(1);
}
// above function will not return until running thread(s) terminate
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: setting service status to stopped.\n"));
status.dwCurrentState = SERVICE_STOPPED;
status.dwCheckPoint = 0;
status.dwWaitHint = 0;
if (!SetServiceStatus(hService, &status))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d setting service status to stopped.\n", GetLastError()));
SnmpSvcReportEvent(SNMP_EVENT_FATAL_ERROR, 0, NULL, GetLastError());
exit(1);
}
} // end serviceMainFunction()
static BOOL breakHandler(
IN ULONG ulType)
{
extern HANDLE gsd;
UNREFERENCED_PARAMETER(ulType);
SNMPDBG((SNMP_LOG_TRACE, "SNMP: SVC: break intercepted, cleaning up...\n"));
if (!CloseHandle(gsd))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: SVC: error on CloseHandle %d\n", GetLastError()));
//not serious error.
}
return FALSE;
} // end breakHandler()
// to simulate service controller functionality when testing as a process
static BOOL StartServiceCtrlLocalDispatcher(LPSERVICE_TABLE_ENTRY junk)
{
DWORD p1=0; LPSTR *p2=NULL;
(*(junk->lpServiceProc))(p1, p2);
return TRUE;
} // end StartServiceCtrlDispatcher()
#ifndef CHICAGO
//--------------------------- PUBLIC PROCEDURES -----------------------------
//---- Win95's WinMain and NT's main are mutually exclusive routines---------
INT _CRTAPI1 main(
IN int argc, //argument count
IN char *argv[]) //argument vector
{
static SERVICE_TABLE_ENTRY serviceStartTable[2] =
{{"SNMP", serviceMainFunction}, {NULL, NULL}};
OSVERSIONINFO OsInfo;
UNREFERENCED_PARAMETER(argc);
UNREFERENCED_PARAMETER(argv);
OsInfo.dwOSVersionInfoSize = sizeof(OSVERSIONINFO);
if (!GetVersionEx(&OsInfo))
exit(1);
switch (OsInfo.dwPlatformId)
{
case VER_PLATFORM_WIN32_NT:
noservice = FALSE;
platformId = VER_PLATFORM_WIN32_NT;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: platform is Windows NT.\n"));
break;
case VER_PLATFORM_WIN32_WINDOWS:
noservice = TRUE;
platformId = VER_PLATFORM_WIN32_WINDOWS;
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: platform in Windows 95.\n"));
break;
default:
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: unsupported platform 0x%x.\n", OsInfo.dwPlatformId));
SnmpSvcReportEvent(SNMP_EVENT_INVALID_PLATFORM_ID, 0, NULL, NO_ERROR);
exit(1);
}
tryagain:
if (noservice) {
// intercept ctrl-c and ctrl-break to allow cleanup to be done
if (!SetConsoleCtrlHandler(breakHandler, TRUE))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on SetConsoleCtrlHandler %d\n", GetLastError()));
//not serious error.
}
}
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: service starting...\n"));
//start service control dispatcher
if (noservice) {
if (!StartServiceCtrlLocalDispatcher(serviceStartTable))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on StartServiceCtrlDispatch %d\n", GetLastError()));
exit(1);
}
} else {
if (!StartServiceCtrlDispatcher(serviceStartTable))
{
if (GetLastError() == 1063) {
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: retry with local service control dispatcher.\n"));
noservice = TRUE;
goto tryagain;
}
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on StartServiceCtrlDispatch %d\n", GetLastError()));
exit(1);
}
}
// above function will not return until running service(s) terminate
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: service terminated.\n"));
return 0;
} // end main()
//-------------------------------- END NT Specific -------------------------------
#else
//------------------------------ Begin Win95 Specific -----------------------------
LRESULT CALLBACK WndProc(
HWND hWnd, // window handle
UINT message, // type of message
WPARAM uParam, // additional information
LPARAM lParam); // additional information
#define SNMP_AGENT_EVENT "SNMP.Agent.Event"
HINSTANCE hInst; // current instance
char szAppName[64]; // The name of this application
char szTitle[32]; // The title bar text
char szHelpStr[32]; // Help flag "Help"
char szQuestStr[32];// Abriev. Help Flag "?"
char szCloseStr[32];// Close flag "close"
char szDestroyStr[32]; //Destroy flag "destroy"
char szHelpText1[256]; //Help String
char szHelpText2[64]; //Help String
char szHelpText3[128]; //Help String
HWND hWnd; // Main window handle.
BOOL InitApplication(HINSTANCE hInstance);
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow);
BOOL GetStrings(HINSTANCE hInstance);
//int APIENTRY WinMain
INT APIENTRY WinMain(
HINSTANCE hInstance,
HINSTANCE hPrevInstance,
LPSTR lpCmdLine,
int nCmdShow)
{
MSG msg;
HANDLE SnmpAgentEvent, hThread, hKernel32 = NULL;
DWORD threadId, LastError;
BOOL fKillParent = FALSE, fRegSrvcProc = FALSE;
FARPROC pRegSrvcProc;
extern HANDLE hExitTrapThreadEvent;
LPCSTR event_name = SNMP_AGENT_EVENT;
DWORD err;
if ((WinVersion = (GetVersion() & 0x000000ff)) == 0x04)
{
if ((hKernel32 = GetModuleHandle("kernel32.dll")) == NULL)
{
// This should never happen but we'll try and load the library anyway
if ((hKernel32 = LoadLibrary("kernel32.dll")) == NULL)
fRegSrvcProc = FALSE;
}
if (hKernel32)
{
if ((pRegSrvcProc = GetProcAddress(hKernel32,"RegisterServiceProcess")) == NULL)
fRegSrvcProc = FALSE;
else
fRegSrvcProc = TRUE;
}
}
else
fRegSrvcProc = FALSE;
//
// Other instances of regserv running?
//
SnmpAgentEvent = OpenEvent(SYNCHRONIZE, FALSE, event_name);
if (SnmpAgentEvent == NULL) {
if ( (SnmpAgentEvent = CreateEvent(NULL, FALSE, TRUE, event_name)) == NULL)
{
LastError = GetLastError();
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: Create Event Failed w/ %d\n", LastError));
return 1;
}
} else {
SnmpAgentEvent = NULL; // another instance is running.
}
if (!GetStrings(hInstance))
{
return 1;
}
platformId = VER_PLATFORM_WIN32_WINDOWS;
// we are not on NT... is our command line setup to kill the parent?
if ( ( lpCmdLine[0]=='-') ||
( lpCmdLine[0]=='/') )
{
// is it CLOSE or DESTROY??
if ( _strnicmp ( &lpCmdLine[1], szCloseStr, strlen(szCloseStr) ) ==0 )
fKillParent = TRUE;
else if ( _strnicmp ( &lpCmdLine[1], szDestroyStr, strlen(szDestroyStr) ) ==0 )
fKillParent = TRUE;
else if (( _strnicmp ( &lpCmdLine[1], szHelpStr, strlen(szHelpStr) )==0 )||
( _strnicmp ( &lpCmdLine[1], szQuestStr, strlen(szQuestStr) )==0 ))
{ // they have asked for help...
MessageBox (GetTopWindow(GetDesktopWindow()),
szHelpText1,
szHelpText2,
MB_OK );
return 0;
}
}
if ((hPrevInstance) ||
(SnmpAgentEvent == NULL))
{
SNMPDBG((SNMP_LOG_ERROR,"SNMP: INIT: service already running\n"));
if (!fKillParent) // if we are not killing the parent, only one agent at a time...
{
HANDLE hParentWin = GetTopWindow(GetDesktopWindow());
MessageBox (hParentWin,
szHelpText3,
szHelpText2,
MB_OK );
return 1;
}
if (hPrevInstance == NULL)
if ( (hPrevInstance = FindWindow(szAppName,NULL)) == NULL)
return 1;
// else send our parent a die message...
PostMessage ( hPrevInstance, WM_CLOSE, 0,0 );
return 0;
}
if (fKillParent)
// no parent to kill
return 2;
if(!InitApplication(hInstance))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: Unable to register window class\n"));
return (FALSE);
}
if (!InitInstance(hInstance, SW_HIDE)) { // ignore nCmdShow
SNMPDBG((SNMP_LOG_ERROR,"SNMP: INIT: Unable to create main window\n"));
return (FALSE);
}
noservice = TRUE;
if ((hThread = CreateThread(NULL, 0,
(LPTHREAD_START_ROUTINE)serviceMainFunction,
NULL, 0, &threadId)) == 0)
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error %d creating main service thread.\n", GetLastError()));
}
else
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: created serviceMainFunction tid=0x%lx.\n", threadId));
}
if (fRegSrvcProc)
(*pRegSrvcProc)(GetCurrentProcessId(), RSP_SIMPLE_SERVICE);
// Acquire and dispatch messages until a WM_QUIT message is received.
while (GetMessage(&msg, NULL, 0, 0)) {
TranslateMessage(&msg); // Translates virtual key codes
DispatchMessage(&msg); // Dispatches message to window
}
if (fRegSrvcProc)
(*pRegSrvcProc)(GetCurrentProcessId(), RSP_UNREGISTER_SERVICE);
// set event causing trap thread to terminate, followed by comm thread
if (!SetEvent(hExitTrapThreadEvent))
{
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: error on SetEvent %d\n", GetLastError()));
}
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: SNMP Service exiting 0\n"));
return(0);
UNREFERENCED_PARAMETER(lpCmdLine);
}
//
// GetStrings - retrieves resource strings from exe
//
BOOL GetStrings(HINSTANCE hInstance)
{
DWORD err, LastError;
if ((err = LoadString(hInstance, IDS_TITLE_BAR, szTitle, sizeof(szTitle))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_APP_NAME, szAppName, sizeof(szAppName))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_HELP_STRING, szHelpStr, sizeof(szHelpStr))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_QUEST_STRING, szQuestStr, sizeof(szQuestStr))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_CLOSE_STRING, szCloseStr, sizeof(szCloseStr))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_DESTROY_STRING, szDestroyStr, sizeof(szDestroyStr))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_HELP_TEXT1, szHelpText1, sizeof(szHelpText1))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_HELP_TEXT2, szHelpText2, sizeof(szHelpText2))) == 0)
{
goto ErrorExit;
}
if ((err = LoadString(hInstance, IDS_HELP_TEXT3, szHelpText3, sizeof(szHelpText3))) == 0)
{
goto ErrorExit;
}
return TRUE;
ErrorExit:
LastError = GetLastError();
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: LoadString Failed w/ %d\n", LastError));
return FALSE;
}
//
// InitInstance - save instance handle and create main window
//
BOOL InitInstance(HINSTANCE hInstance, int nCmdShow)
{
// Save the instance handle in static variable, which will be used in
// many subsequence calls from this application to Windows.
hInst = hInstance; // Store instance handle in our global variable
// Create a main window for this application instance.
hWnd = CreateWindow(
szAppName,
szTitle,
WS_EX_TRANSPARENT, // Window style.
0, 0, CW_USEDEFAULT, CW_USEDEFAULT, // Use default positioning CW_USEDEAULT
NULL, // Overlapped windows have no parent.
NULL, // Use the window class menu.
hInstance, // This instance owns this window.
NULL // We don't use any data in our WM_CREATE
);
// If window could not be created, return "failure"
if (!hWnd) {
return (FALSE);
}
// Make the window visible; update its client area; and return "success"
ShowWindow(hWnd, nCmdShow); // Show the window
UpdateWindow(hWnd); // Sends WM_PAINT message
return (TRUE); // We succeeded...
}
//
// InitApplication - initialize window data and register window class
//
// Return - NULL => failure
//
BOOL InitApplication(HINSTANCE hInstance)
{
WNDCLASS wc;
DWORD LastError;
// Fill in window class structure with parameters that describe the
// main window.
wc.style = CS_HREDRAW | CS_VREDRAW;// Class style(s).
wc.lpfnWndProc = (WNDPROC)WndProc; // Window Procedure
wc.cbClsExtra = 0; // No per-class extra data.
wc.cbWndExtra = 0; // No per-window extra data.
wc.hInstance = hInstance; // Owner of this class
wc.hIcon = NULL;
wc.hCursor = NULL;
wc.hbrBackground = (HBRUSH)(COLOR_WINDOW+1);// Default color
wc.lpszMenuName = szAppName; // Menu name from .RC
wc.lpszClassName = szAppName; // Name to register as
// Register the window class and return success/failure code.
if (!RegisterClass(&wc))
{
LastError = GetLastError();
SNMPDBG((SNMP_LOG_ERROR, "SNMP: INIT: RegisterClass failed w/ %d\n", LastError ));
return FALSE;
}
else
return TRUE;
}
//
// WndProc - process messages
//
LRESULT CALLBACK WndProc(
HWND hWnd, // window handle
UINT message, // type of message
WPARAM uParam, // additional information
LPARAM lParam) // additional information
{
switch (message)
{
case WM_ENDSESSION:
case WM_QUERYENDSESSION:
if (lParam == 0)
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: Received shutdown message\n"));
}
if (lParam == 1 ) //EWX_REALLYLOGOFF
{
SNMPDBG((SNMP_LOG_TRACE, "SNMP: INIT: Received logoff message\n"));
}
return(1);
case WM_DESTROY: // message: window being destroyed
PostQuitMessage(0);
return(0);
default: // Pass it on if unproccessed
return (DefWindowProc(hWnd, message, uParam, lParam));
}
}
#endif