|
|
/*++
Copyright (c) 1991 Microsoft Corporation
Module Name:
ts3.c
Abstract:
This is a test program for exercising the service controller. This program acts like a service and exercises the Service Controller API that can be called from a service: SetServiceStatus StartServiceCtrlDispatcher RegisterServiceCtrlHandler
Author:
Dan Lafferty (danl) 2 Apr-1992
Environment:
User Mode -Win32
Revision History:
--*/
//
// Includes
//
#include <nt.h> // DbgPrint prototype
#include <ntrtl.h> // DbgPrint prototype
#include <nturtl.h> // needed for winbase.h
#include <windows.h>
#include <winsvc.h>
#include <stdio.h>
#include <stdlib.h>
#include <fcntl.h> // OpenFile
#include <sys\types.h> // OpenFile
#include <sys\stat.h> // OpenFile
#include <io.h> // OpenFile
#include <tstr.h> // Unicode string macros
#include <rpc.h>
//
// Defines
//
#define INFINITE_WAIT_TIME 0xffffffff
#define NULL_STRING TEXT("");
//
// Globals
//
SERVICE_STATUS SingleStatus;
HANDLE SingleDoneEvent;
SERVICE_STATUS_HANDLE SingleStatusHandle;
//
// Function Prototypes
//
VOID SingleStart ( DWORD argc, LPTSTR *argv );
VOID SingleCtrlHandler ( IN DWORD opcode );
DWORD GetIntlFormat( LPWSTR type, LPWSTR string, DWORD numChars);
VOID GetTime( LPWSTR *time );
/****************************************************************************/ VOID __cdecl main(void) { DWORD status;
SERVICE_TABLE_ENTRY DispatchTable[] = { { TEXT("single"), SingleStart }, { TEXT("single1"), SingleStart }, // this entry should be ignored.
{ NULL, NULL } }; if (!StartServiceCtrlDispatcher( DispatchTable)) { status = GetLastError(); DbgPrint("[ts3]StartServiceCtrlDispatcher failed %d \n",status); if (status = ERROR_FAILED_SERVICE_CONTROLLER_CONNECT) { printf("Failed to connect to service controller, this " "program should be started with the Services Control Panel Applet, " "or at the command line with Net Start <ServiceName>"); } }
DbgPrint("[ts3]The Service Process is Terminating....)\n");
ExitProcess(0);
}
/****************************************************************************/
//
// Single will take a long time to respond to pause
//
//
VOID SingleStart ( DWORD argc, LPTSTR *argv ) { DWORD status; DWORD i; NETRESOURCEW netResource;
DbgPrint(" [SINGLE] Inside the Single Service Thread\n");
for (i=0; i<argc; i++) { DbgPrint(" [SINGLE] CommandArg%d = %s\n", i,argv[i]); }
SingleDoneEvent = CreateEvent (NULL, TRUE, FALSE,NULL);
//
// Fill in this services status structure
//
DbgPrint(" [SINGLE] Send status with ServiceType = SERVICE_WIN32\n" " This should not overwrite the copy that SC maintains\n" " which should be SERVICE_WIN32_OWN_PROCESS\n");
SingleStatus.dwServiceType = SERVICE_WIN32; SingleStatus.dwCurrentState = SERVICE_RUNNING; SingleStatus.dwControlsAccepted = SERVICE_ACCEPT_STOP | SERVICE_ACCEPT_PAUSE_CONTINUE; SingleStatus.dwWin32ExitCode = 0; SingleStatus.dwServiceSpecificExitCode = 0; SingleStatus.dwCheckPoint = 0; SingleStatus.dwWaitHint = 0; //
// Register the Control Handler routine.
//
DbgPrint(" [SINGLE] Getting Ready to call RegisterServiceCtrlHandler\n");
SingleStatusHandle = RegisterServiceCtrlHandler( TEXT("single"), SingleCtrlHandler);
if (SingleStatusHandle == (SERVICE_STATUS_HANDLE)0) { DbgPrint(" [SINGLE] RegisterServiceCtrlHandler failed %d\n", GetLastError()); } //
// Return the status
//
if (!SetServiceStatus (SingleStatusHandle, &SingleStatus)) { status = GetLastError(); DbgPrint(" [SINGLE] SetServiceStatus error %ld\n",status); }
//================================
// SPECIAL TEST GOES HERE.
//================================
#define TEST_USE_ADD
#ifdef TEST_USE_ADD
netResource.lpRemoteName = L"\\\\Kernel\\scratch"; netResource.lpLocalName = L"z:"; netResource.lpProvider = NULL; netResource.dwType = RESOURCETYPE_DISK;
status = WNetAddConnection2W(&netResource, NULL, NULL, 0L); if (status != NO_ERROR) { DbgPrint("WNetAddConnection (z:) Failed %d\n",status); }
netResource.lpRemoteName = L"\\\\popcorn\\public"; netResource.lpLocalName = L"p:"; netResource.lpProvider = NULL; netResource.dwType = RESOURCETYPE_DISK;
status = WNetAddConnection2W(&netResource, NULL, NULL, 0L); if (status != NO_ERROR) { DbgPrint("WNetAddConnection (p:) Failed %d\n",status); } #endif
{ UUID Uuid; RPC_STATUS rpcstatus;
rpcstatus = UuidCreate(&Uuid); if (rpcstatus != NO_ERROR) { DbgPrint("UuidCreate Failed %d \n",rpcstatus); } }
//
// Wait forever until we are told to terminate.
//
{
//
// This portion of the code determines that the working directory
// is the system32 directory.
//
LPSTR String = GetEnvironmentStrings(); DWORD rc;
Sleep(1000); while (*String != 0) { DbgPrint("%s\n",String); String += (strlen(String) + 1); } rc = _open("DansFile.txt",O_CREAT | O_BINARY,S_IREAD | S_IWRITE); if (rc == -1) { DbgPrint("OpenFile Failed\n"); } }
status = WaitForSingleObject ( SingleDoneEvent, INFINITE_WAIT_TIME);
status = WNetCancelConnectionW(L"z:",FALSE); if (status != NO_ERROR) { DbgPrint("WNetCancelConnection (z:) Failed %d\n",status); } status = WNetCancelConnectionW(L"p:",FALSE); if (status != NO_ERROR) { DbgPrint("WNetCancelConnection (p:) Failed %d\n",status); }
DbgPrint(" [SINGLE] Leaving the single service\n");
ExitThread(NO_ERROR); return; }
/****************************************************************************/ VOID SingleCtrlHandler ( IN DWORD Opcode ) {
DWORD status; LPWSTR time;
HANDLE enumHandle; DWORD numElements; DWORD bufferSize; LPNETRESOURCE pNetResource; DWORD i;
DbgPrint(" [SINGLE] opcode = %ld\n", Opcode);
//
// Find and operate on the request.
//
switch(Opcode) { case SERVICE_CONTROL_PAUSE:
DbgPrint("[SINGLE] Sleep 1 minute before responding to pause request\n"); Sleep(60000); // 1 minute
SingleStatus.dwCurrentState = SERVICE_PAUSED; break;
case SERVICE_CONTROL_CONTINUE:
SingleStatus.dwCurrentState = SERVICE_RUNNING; break;
case SERVICE_CONTROL_STOP:
SingleStatus.dwWin32ExitCode = 0; SingleStatus.dwCurrentState = SERVICE_STOPPED;
SetEvent(SingleDoneEvent); break;
case SERVICE_CONTROL_INTERROGATE: status = WNetOpenEnumW( RESOURCE_CONNECTED, RESOURCETYPE_DISK, 0, NULL, &enumHandle);
if (status != WN_SUCCESS) { DbgPrint("WNetOpenEnum failed %d\n",status); } else { //
// Attempt to allow for 10 connections
//
bufferSize = (10*sizeof(NETRESOURCE))+1024; pNetResource = (LPNETRESOURCE) LocalAlloc(LPTR, bufferSize);
if (pNetResource == NULL) { DbgPrint("TestEnum:LocalAlloc Failed %d\n",GetLastError); break; } numElements = 0xffffffff; status = WNetEnumResourceW( enumHandle, &numElements, pNetResource, &bufferSize);
if ( status != WN_SUCCESS) { DbgPrint("WNetEnumResource failed %d\n",status); //
// If there is an extended error, display it.
//
if (status == WN_EXTENDED_ERROR) { DbgPrint("Extended Error\n"); } WNetCloseEnum(enumHandle); LocalFree(pNetResource); } else { if (numElements == 0) { DbgPrint("No Connections to Enumerate\n"); } for (i=0; i < numElements ;i++ ) { DbgPrint("%ws is connected to %ws\n", pNetResource[i].lpLocalName, pNetResource[i].lpRemoteName);
} WNetCloseEnum(enumHandle); LocalFree(pNetResource); } } GetTime(&time); DbgPrint(" [SINGLE] time = %ws\n",time); break;
default: DbgPrint(" [SINGLE] Unrecognized opcode %ld\n", Opcode); }
//
// Send a status response.
//
if (!SetServiceStatus (SingleStatusHandle, &SingleStatus)) { status = GetLastError(); DbgPrint(" [SINGLE] SetServiceStatus error %ld\n",status); } return; }
//************************************************************************
//
// TEST CODE
//
//************************************************************************
#define PARSE_SIZE 80
#define TIME_SEP_SIZE 2
VOID GetTime( LPWSTR *time ) { WCHAR czParseString[PARSE_SIZE]; WCHAR czTimeString[PARSE_SIZE]; LPWSTR pCurLoc; LPWSTR pTime; DWORD numChars; SYSTEMTIME SysTime; LPWSTR AMPMString=L""; WCHAR TimeSep[TIME_SEP_SIZE]; BOOL TwelveHour=TRUE; BOOL LeadingZero=FALSE; DWORD i,dateType; DWORD numSame;
//-----------------------------------------
// Get the Current Time and Date.
//-----------------------------------------
GetLocalTime(&SysTime);
#ifdef CL_DEBUG
printf("Year=%d,Month=%d,Day=%d,Hour=%d,Minute=%d\n", SysTime.wYear, SysTime.wMonth, SysTime.wDay, SysTime.wHour, SysTime.wMinute); #endif
//-----------------------------------------
// Get the Date Format (M/d/yy)
//-----------------------------------------
numChars = GetIntlFormat(L"sShortDate",czParseString,PARSE_SIZE); if (numChars == 0) { //
// No data, use the default.
//
wcscpy(czParseString, L"M/d/yy"); }
//-----------------------------------------
// Fill in the date string
//-----------------------------------------
pCurLoc = czTimeString;
for (i=0; i<numChars; i++ ) {
dateType = i; numSame = 1;
//
// Find out how many characters are the same.
// (MM or M, dd or d, yy or yyyy)
//
while (czParseString[i] == czParseString[i+1]) { numSame++; i++; }
//
// i is the offset to the last character in the date type.
//
switch (czParseString[dateType]) { case L'M': case L'm': //
// If we have a single digit month, but require 2 digits,
// then add a leading zero.
//
if ((numSame == 2) && (SysTime.wMonth < 10)) { *pCurLoc = L'0'; pCurLoc++; } ultow(SysTime.wMonth, pCurLoc, 10); pCurLoc += wcslen(pCurLoc); break;
case L'D': case L'd':
//
// If we have a single digit day, but require 2 digits,
// then add a leading zero.
//
if ((numSame == 2) && (SysTime.wDay < 10)) { *pCurLoc = L'0'; pCurLoc++; } ultow(SysTime.wDay, pCurLoc, 10); pCurLoc += wcslen(pCurLoc); break;
case L'Y': case L'y':
ultow(SysTime.wYear, pCurLoc, 10); //
// If we are only to show 2 digits, take the
// 3rd and 4th, and move them into the first two
// locations.
//
if (numSame == 2) { pCurLoc[0] = pCurLoc[2]; pCurLoc[1] = pCurLoc[3]; pCurLoc[2] = L'\0'; } pCurLoc += wcslen(pCurLoc); break;
default: printf("Default case: Unrecognized time character - " "We Should never get here\n"); break; } //
// Increment the index beyond the last character in the data type.
// If not at the end of the buffer, add the separator character.
// Otherwise, add the trailing NUL.
//
i++; if ( i<numChars ) { *pCurLoc = czParseString[i]; pCurLoc++; } else { *pCurLoc='\0'; } }
//-----------------------------------------
// 12 or 24 hour format?
//-----------------------------------------
numChars = GetIntlFormat(L"iTime",czParseString,PARSE_SIZE); if (numChars > 0) { if (*czParseString == L'1'){ TwelveHour = FALSE; } }
//-----------------------------------------
// Is there a Leading Zero?
//-----------------------------------------
if (GetProfileIntW(L"intl",L"iTLZero",0) == 1) { LeadingZero = TRUE; }
//-----------------------------------------
// Get the Time Separator character.
//-----------------------------------------
numChars = GetIntlFormat(L"sTime",TimeSep,TIME_SEP_SIZE); if (numChars == 0) { //
// No data, use the default.
//
TimeSep[0] = L':'; TimeSep[1] = L'\0'; }
//-------------------------------------------------
// If running a 12 hour clock, Get the AMPM string.
//-------------------------------------------------
if (TwelveHour) { if (SysTime.wHour > 11) { numChars = GetIntlFormat(L"s2359",czParseString,PARSE_SIZE); } else { numChars = GetIntlFormat(L"s1159",czParseString,PARSE_SIZE); } if (numChars > 0) { AMPMString = LocalAlloc(LMEM_FIXED,wcslen(czParseString)+sizeof(WCHAR)); if (AMPMString != NULL) { wcscpy(AMPMString,czParseString); } } }
//
// Build the time string
//
pTime = czTimeString + (wcslen(czTimeString) + 1);
if ((TwelveHour) && (SysTime.wHour > 12)) { SysTime.wHour -= 12; } //
// If the time is a single digit, and we need a leading zero,
// than add the leading zero.
//
if ((SysTime.wHour < 10) && (LeadingZero)) { *pTime = L'0'; pTime++; } ultow(SysTime.wHour, pTime, 10); pTime += wcslen(pTime); *pTime = *TimeSep; pTime++; if (SysTime.wMinute < 10) { *pTime = L'0'; pTime++; } ultow(SysTime.wMinute, pTime, 10); wcscat(pTime,AMPMString);
pTime = czTimeString + (wcslen(czTimeString) + 1);
#ifdef CL_DEBUG
printf("Time = %ws, Date = %ws\n",pTime,czTimeString); #endif
*(--pTime) = L' '; printf("\n %ws\n", czTimeString); *time = czTimeString; }
DWORD GetIntlFormat( LPWSTR type, LPWSTR string, DWORD numChars) { DWORD num;
num = GetProfileStringW(L"intl",type,L"",string,numChars);
#ifdef CL_DEBUG
if (num > 0) { printf("%ws string from ini file = %ws\n",type, string); } else { printf("%ws string from ini file = (empty)\n",type); } #endif
return(num); }
|