windows-nt/Source/XPSP1/NT/base/screg/sc/client/ts3.c

638 lines
16 KiB
C
Raw Normal View History

2020-09-26 03:20:57 -05:00
/*++
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);
}