Leaked source code of windows server 2003
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.
 
 
 
 
 
 

689 lines
17 KiB

/*++
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.
if Message(comment) is longer than MAX_REASON_COMMENT_LEN
return FALSE.(ERROR_INVALID_PARAMETER)
dwTimeout - Number of seconds to delay before shutting down
if dwTimeout is larger than MAX_SHUTDOWN_TIMEOUT,
return FALSE. (ERROR_INVALID_PARAMETER)
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);
if ( ( Message.Length / sizeof(WCHAR) < MAX_REASON_COMMENT_LEN ) &&
( dwTimeout < MAX_SHUTDOWN_TIMEOUT ) ){
//
// 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);
}
}
else{
Result = ERROR_INVALID_PARAMETER;
}
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.
if Message(comment) is longer than MAX_REASON_COMMENT_LEN
return FALSE.(ERROR_INVALID_PARAMETER)
dwTimeout - Number of seconds to delay before shutting down
if dwTimeout is larger than MAX_SHUTDOWN_TIMEOUT,
return FALSE. (ERROR_INVALID_PARAMETER)
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);
if ( ( Message.Length / sizeof(WCHAR) < MAX_REASON_COMMENT_LEN ) &&
( dwTimeout < MAX_SHUTDOWN_TIMEOUT ) ) {
//
// 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);
}
}
else{
Result = ERROR_INVALID_PARAMETER;
}
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);
}