|
|
/*++
Copyright (c) 1992 Microsoft Corporation
Module Name:
Shutdown.c
Abstract:
This module contains the client side wrappers for the Win32 remote shutdown APIs, that is:
- InitiateSystemShutdownA - InitiateSystemShutdownW - AbortSystemShutdownA - AbortSystemShutdownW
Author:
Dave Chalmers (davidc) 29-Apr-1992
Notes:
Revision History: Dragos C. Sambotin (dragoss) 21-May-1999 Added support for the new winlogon's Shutdown interface
--*/
#define UNICODE
#include <rpc.h>
#include "regrpc.h"
#include "client.h"
#include "shutinit.h"
#include "..\regconn\regconn.h"
LONG BaseBindToMachine( IN LPCWSTR lpMachineName, IN PBIND_CALLBACK BindCallback, IN PVOID Context1, IN PVOID Context2 );
LONG ShutdownCallback( IN RPC_BINDING_HANDLE *pbinding, IN PUNICODE_STRING Message, IN PVOID Context2 );
LONG ShutdownCallbackEx( IN RPC_BINDING_HANDLE *pbinding, IN PUNICODE_STRING Message, IN PVOID Context2 );
LONG AbortShutdownCallback( IN RPC_BINDING_HANDLE *pbinding, IN PVOID Context1, IN PVOID Context2 );
BOOL APIENTRY InitiateSystemShutdownW( IN LPWSTR lpMachineName OPTIONAL, IN LPWSTR lpMessage OPTIONAL, IN DWORD dwTimeout, IN BOOL bForceAppsClosed, IN BOOL bRebootAfterShutdown )
/*++
Routine Description:
Win32 Unicode API for initiating the shutdown of a (possibly remote) machine.
Arguments:
lpMachineName - Name of machine to shutdown.
lpMessage - Message to display during shutdown timeout period.
dwTimeout - Number of seconds to delay before shutting down
bForceAppsClosed - Normally applications may prevent system shutdown. If this flag is set, all applications are terminated unconditionally.
bRebootAfterShutdown - TRUE if the system should reboot. FALSE if it should be left in a shutdown state.
Return Value:
Returns TRUE on success, FALSE on failure (GetLastError() returns error code)
Possible errors :
ERROR_SHUTDOWN_IN_PROGRESS - a shutdown has already been started on the specified machine.
--*/
{ DWORD Result; UNICODE_STRING Message; SHUTDOWN_CONTEXT ShutdownContext; BOOL TryOld = TRUE;
//
// Explicitly bind to the given server.
//
if (!ARGUMENT_PRESENT(lpMachineName)) { lpMachineName = L""; TryOld = FALSE; }
ShutdownContext.dwTimeout = dwTimeout; ShutdownContext.bForceAppsClosed = (bForceAppsClosed != 0); ShutdownContext.bRebootAfterShutdown = (bRebootAfterShutdown != 0); RtlInitUnicodeString(&Message, lpMessage);
//
// Call the server
//
//
// First try to connect to the new InitShutdown interface
//
Result = BaseBindToMachineShutdownInterface(lpMachineName, NewShutdownCallback, &Message, &ShutdownContext);
if( (Result != ERROR_SUCCESS) && (TryOld == TRUE) ) { //
// try the old one, maybe we are calling into a NT4 machine
// which doesn't know about the new interface
//
Result = BaseBindToMachine(lpMachineName, ShutdownCallback, &Message, &ShutdownContext); }
if (Result != ERROR_SUCCESS) { SetLastError(Result); }
return(Result == ERROR_SUCCESS); }
BOOL APIENTRY InitiateSystemShutdownExW( IN LPWSTR lpMachineName OPTIONAL, IN LPWSTR lpMessage OPTIONAL, IN DWORD dwTimeout, IN BOOL bForceAppsClosed, IN BOOL bRebootAfterShutdown, IN DWORD dwReason )
/*++
Routine Description:
Win32 Unicode API for initiating the shutdown of a (possibly remote) machine.
Arguments:
lpMachineName - Name of machine to shutdown.
lpMessage - Message to display during shutdown timeout period.
dwTimeout - Number of seconds to delay before shutting down
bForceAppsClosed - Normally applications may prevent system shutdown. If this flag is set, all applications are terminated unconditionally.
bRebootAfterShutdown - TRUE if the system should reboot. FALSE if it should be left in a shutdown state.
dwReason - Reason for initiating the shutdown. This reason is logged in the eventlog #6006 event.
Return Value:
Returns TRUE on success, FALSE on failure (GetLastError() returns error code)
Possible errors :
ERROR_SHUTDOWN_IN_PROGRESS - a shutdown has already been started on the specified machine.
--*/
{ DWORD Result; UNICODE_STRING Message; SHUTDOWN_CONTEXTEX ShutdownContext; BOOL TryOld = TRUE;
//
// Explicitly bind to the given server.
//
if (!ARGUMENT_PRESENT(lpMachineName)) { lpMachineName = L""; TryOld = FALSE; }
ShutdownContext.dwTimeout = dwTimeout; ShutdownContext.bForceAppsClosed = (bForceAppsClosed != 0); ShutdownContext.bRebootAfterShutdown = (bRebootAfterShutdown != 0); ShutdownContext.dwReason = dwReason; RtlInitUnicodeString(&Message, lpMessage);
//
// Call the server
//
//
// First try to connect to the new InitShutdown interface
//
Result = BaseBindToMachineShutdownInterface(lpMachineName, NewShutdownCallbackEx, &Message, &ShutdownContext);
if( (Result != ERROR_SUCCESS) && (TryOld == TRUE) ) { //
// try the old one, maybe we are calling into a NT4 machine
// which doesn't know about the new interface
//
Result = BaseBindToMachine(lpMachineName, ShutdownCallbackEx, &Message, &ShutdownContext); }
if (Result != ERROR_SUCCESS) { SetLastError(Result); }
return(Result == ERROR_SUCCESS); }
BOOL APIENTRY InitiateSystemShutdownA( IN LPSTR lpMachineName OPTIONAL, IN LPSTR lpMessage OPTIONAL, IN DWORD dwTimeout, IN BOOL bForceAppsClosed, IN BOOL bRebootAfterShutdown )
/*++
Routine Description:
See InitiateSystemShutdownW
--*/
{ UNICODE_STRING MachineName; UNICODE_STRING Message; ANSI_STRING AnsiString; NTSTATUS Status; BOOL Result;
//
// Convert the ansi machinename to wide-character
//
RtlInitAnsiString( &AnsiString, lpMachineName ); Status = RtlAnsiStringToUnicodeString( &MachineName, &AnsiString, TRUE );
if( NT_SUCCESS( Status )) {
//
// Convert the ansi message to wide-character
//
RtlInitAnsiString( &AnsiString, lpMessage ); Status = RtlAnsiStringToUnicodeString( &Message, &AnsiString, TRUE );
if (NT_SUCCESS(Status)) {
//
// Call the wide-character api
//
Result = InitiateSystemShutdownW( MachineName.Buffer, Message.Buffer, dwTimeout, bForceAppsClosed, bRebootAfterShutdown );
RtlFreeUnicodeString(&Message); }
RtlFreeUnicodeString(&MachineName); }
if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); Result = FALSE; }
return(Result); }
BOOL APIENTRY InitiateSystemShutdownExA( IN LPSTR lpMachineName OPTIONAL, IN LPSTR lpMessage OPTIONAL, IN DWORD dwTimeout, IN BOOL bForceAppsClosed, IN BOOL bRebootAfterShutdown, IN DWORD dwReason )
/*++
Routine Description:
See InitiateSystemShutdownW
--*/
{ UNICODE_STRING MachineName; UNICODE_STRING Message; ANSI_STRING AnsiString; NTSTATUS Status; BOOL Result;
//
// Convert the ansi machinename to wide-character
//
RtlInitAnsiString( &AnsiString, lpMachineName ); Status = RtlAnsiStringToUnicodeString( &MachineName, &AnsiString, TRUE );
if( NT_SUCCESS( Status )) {
//
// Convert the ansi message to wide-character
//
RtlInitAnsiString( &AnsiString, lpMessage ); Status = RtlAnsiStringToUnicodeString( &Message, &AnsiString, TRUE );
if (NT_SUCCESS(Status)) {
//
// Call the wide-character api
//
Result = InitiateSystemShutdownExW( MachineName.Buffer, Message.Buffer, dwTimeout, bForceAppsClosed, bRebootAfterShutdown, dwReason );
RtlFreeUnicodeString(&Message); }
RtlFreeUnicodeString(&MachineName); }
if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); Result = FALSE; }
return(Result); }
BOOL APIENTRY AbortSystemShutdownW( IN LPWSTR lpMachineName OPTIONAL )
/*++
Routine Description:
Win32 Unicode API for aborting the shutdown of a (possibly remote) machine.
Arguments:
lpMachineName - Name of target machine.
Return Value:
Returns TRUE on success, FALSE on failure (GetLastError() returns error code)
--*/
{ DWORD Result; RPC_BINDING_HANDLE binding; BOOL TryOld = TRUE;
//
// Explicitly bind to the given server.
//
if (!ARGUMENT_PRESENT(lpMachineName)) { lpMachineName = L""; TryOld = FALSE; }
//
// Call the server
//
//
// First try to connect to the new InitShutdown interface
//
Result = BaseBindToMachineShutdownInterface(lpMachineName, NewAbortShutdownCallback, NULL, NULL);
if( (Result != ERROR_SUCCESS) && (TryOld == TRUE) ) { //
// try the old one, maybe we are calling into a NT4 machine
// which doesn't know about the new interface
Result = BaseBindToMachine(lpMachineName, AbortShutdownCallback, NULL, NULL); }
if (Result != ERROR_SUCCESS) { SetLastError(Result); }
return(Result == ERROR_SUCCESS); }
BOOL APIENTRY AbortSystemShutdownA( IN LPSTR lpMachineName OPTIONAL )
/*++
Routine Description:
See AbortSystemShutdownW
--*/
{ UNICODE_STRING MachineName; ANSI_STRING AnsiString; NTSTATUS Status; BOOL Result;
//
// Convert the ansi machinename to wide-character
//
RtlInitAnsiString( &AnsiString, lpMachineName ); Status = RtlAnsiStringToUnicodeString( &MachineName, &AnsiString, TRUE );
if( NT_SUCCESS( Status )) {
//
// Call the wide-character api
//
Result = AbortSystemShutdownW( MachineName.Buffer );
RtlFreeUnicodeString(&MachineName); }
if (!NT_SUCCESS(Status)) { SetLastError(RtlNtStatusToDosError(Status)); Result = FALSE; }
return(Result); }
LONG ShutdownCallback( IN RPC_BINDING_HANDLE *pbinding, IN PUNICODE_STRING Message, IN PSHUTDOWN_CONTEXT ShutdownContext ) /*++
Routine Description:
Callback for binding to a machine to initiate a shutdown.
Arguments:
pbinding - Supplies a pointer to the RPC binding context
Message - Supplies message to display during shutdown timeout period.
ShutdownContext - Supplies remaining parameters for BaseInitiateSystemShutdown
Return Value:
ERROR_SUCCESS if no error.
--*/
{ DWORD Result;
RpcTryExcept { Result = BaseInitiateSystemShutdown((PREGISTRY_SERVER_NAME)pbinding, Message, ShutdownContext->dwTimeout, ShutdownContext->bForceAppsClosed, ShutdownContext->bRebootAfterShutdown); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Result = RpcExceptionCode(); } RpcEndExcept;
if (Result != ERROR_SUCCESS) { RpcBindingFree(pbinding); } return(Result); }
LONG ShutdownCallbackEx( IN RPC_BINDING_HANDLE *pbinding, IN PUNICODE_STRING Message, IN PSHUTDOWN_CONTEXTEX ShutdownContext ) /*++
Routine Description:
Callback for binding to a machine to initiate a shutdown.
Arguments:
pbinding - Supplies a pointer to the RPC binding context
Message - Supplies message to display during shutdown timeout period.
ShutdownContext - Supplies remaining parameters for BaseInitiateSystemShutdown
Return Value:
ERROR_SUCCESS if no error.
--*/
{ DWORD Result;
RpcTryExcept { Result = BaseInitiateSystemShutdownEx((PREGISTRY_SERVER_NAME)pbinding, Message, ShutdownContext->dwTimeout, ShutdownContext->bForceAppsClosed, ShutdownContext->bRebootAfterShutdown, ShutdownContext->dwReason); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Result = RpcExceptionCode(); } RpcEndExcept;
if (Result != ERROR_SUCCESS) { RpcBindingFree(pbinding); } return(Result); }
LONG AbortShutdownCallback( IN RPC_BINDING_HANDLE *pbinding, IN PVOID Unused1, IN PVOID Unused2 ) /*++
Routine Description:
Callback for binding to a machine to abort a shutdown.
Arguments:
pbinding - Supplies a pointer to the RPC binding context
Return Value:
ERROR_SUCCESS if no error.
--*/
{ DWORD Result;
RpcTryExcept { Result = BaseAbortSystemShutdown((PREGISTRY_SERVER_NAME)pbinding); } RpcExcept(EXCEPTION_EXECUTE_HANDLER) { Result = RpcExceptionCode(); } RpcEndExcept;
if (Result != ERROR_SUCCESS) { RpcBindingFree(pbinding); } return(Result); }
|