792 lines
30 KiB
C++
792 lines
30 KiB
C++
//*****************************************************************************
|
|
// Copyright (C) Microsoft Corporation
|
|
// All rights reserved.
|
|
//*****************************************************************************
|
|
#include "stdafx.h"
|
|
|
|
#define WSMAN_API_VERSION_1_1
|
|
#include <wsman.h>
|
|
|
|
BOOL APIENTRY DllMain( HMODULE hModule,
|
|
DWORD ul_reason_for_call,
|
|
LPVOID lpReserved
|
|
)
|
|
{
|
|
switch (ul_reason_for_call)
|
|
{
|
|
case DLL_PROCESS_ATTACH:
|
|
case DLL_THREAD_ATTACH:
|
|
case DLL_THREAD_DETACH:
|
|
case DLL_PROCESS_DETACH:
|
|
break;
|
|
}
|
|
return TRUE;
|
|
}
|
|
|
|
#define URI_SHELL_CMD L"http://microsoft.test/shelltestresource"
|
|
|
|
static WSMAN_OPTION noProfileOption =
|
|
{
|
|
WSMAN_SHELL_OPTION_NOPROFILE,
|
|
L"TRUE",
|
|
FALSE
|
|
};
|
|
static WSMAN_OPTION_SET noProfileOptionSet =
|
|
{
|
|
1,
|
|
&noProfileOption,
|
|
FALSE
|
|
};
|
|
|
|
class ShellClient
|
|
{
|
|
public:
|
|
ShellClient()
|
|
:
|
|
shellHandle(NULL),
|
|
shellCreated(NULL),
|
|
shellCreatedCount(0),
|
|
shellCreatedError(NO_ERROR),
|
|
|
|
shellDeleted(NULL),
|
|
shellDeletedCount(0),
|
|
shellDeletedError(NO_ERROR),
|
|
|
|
shellDisconnected(NULL),
|
|
shellDisconnectedCount(0),
|
|
shellDisconnectedError(NO_ERROR),
|
|
|
|
shellReconnected(NULL),
|
|
shellReconnectedCount(0),
|
|
shellReconnectedError(NO_ERROR),
|
|
|
|
shellConnected(NULL),
|
|
shellConnectedCount(0),
|
|
shellConnectedError(NO_ERROR),
|
|
|
|
commandHandle(NULL),
|
|
commandCreated(NULL),
|
|
commandCreatedCount(0),
|
|
commandCreatedError(NO_ERROR),
|
|
|
|
commandDeleted(NULL),
|
|
commandDeletedCount(0),
|
|
commandDeletedError(NO_ERROR),
|
|
|
|
commandConnected(NULL),
|
|
commandConnectedCount(0),
|
|
commandConnectedError(NO_ERROR),
|
|
|
|
signalHandle(NULL),
|
|
signal(NULL),
|
|
signalCount(0),
|
|
signalError(NO_ERROR),
|
|
|
|
receiveHandle(NULL),
|
|
receive(NULL),
|
|
receiveCount(0),
|
|
receiveError(NO_ERROR),
|
|
receiveEndOfStreamCount(0),
|
|
receiveSignalEveryResult(false),
|
|
receiveByteCount(0),
|
|
|
|
sendHandle(NULL),
|
|
send(NULL),
|
|
sendCount(0),
|
|
sendError(NO_ERROR),
|
|
|
|
apiHandle(NULL),
|
|
session(NULL),
|
|
idleTimeout(1000),
|
|
shellUri(URI_SHELL_CMD),
|
|
|
|
shellName(NULL)
|
|
{
|
|
ZeroMemory(receiveBuffer, sizeof(receiveBuffer));
|
|
}
|
|
~ShellClient()
|
|
{
|
|
if (session)
|
|
{
|
|
WSManCloseSession(session, 0);
|
|
}
|
|
if (apiHandle)
|
|
{
|
|
WSManDeinitialize(apiHandle, 0);
|
|
}
|
|
if (shellCreated)
|
|
CloseHandle(shellCreated);
|
|
if (shellDeleted)
|
|
CloseHandle(shellDeleted);
|
|
if (shellDisconnected)
|
|
CloseHandle(shellDisconnected);
|
|
if (shellReconnected)
|
|
CloseHandle(shellReconnected);
|
|
if (shellConnected)
|
|
CloseHandle(shellConnected);
|
|
if (commandCreated)
|
|
CloseHandle(commandCreated);
|
|
if (commandDeleted)
|
|
CloseHandle(commandDeleted);
|
|
if (commandConnected)
|
|
CloseHandle(commandConnected);
|
|
if (signal)
|
|
CloseHandle(signal);
|
|
if (receive)
|
|
CloseHandle(receive);
|
|
if (send)
|
|
CloseHandle(send);
|
|
}
|
|
bool Initialize()
|
|
{
|
|
//Create Events to synchronize WSMan Async APIs
|
|
shellCreated = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
shellDeleted = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
shellDisconnected = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
shellReconnected = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
shellConnected = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
commandCreated = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
commandDeleted = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
commandConnected = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
signal = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
receive = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
send = CreateEvent(NULL, FALSE, FALSE, NULL);
|
|
|
|
//INITIALIZE WSMAN CLIENT
|
|
if (!WSManInitialize(WSMAN_FLAG_REQUESTED_API_VERSION_1_1, &apiHandle))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
WSMAN_AUTHENTICATION_CREDENTIALS creds;
|
|
ZeroMemory(&creds, sizeof(WSMAN_AUTHENTICATION_CREDENTIALS));
|
|
/*Use the following to set authentication information
|
|
creds.authenticationMechanism = authFlag;
|
|
creds.userAccount.username = username;
|
|
creds.userAccount.password = password;
|
|
userPassCreds->certificateThumbprint = thumbprint;
|
|
userPassCreds->authenticationMechanism = WSMAN_FLAG_AUTH_CLIENT_CERTIFICATE;
|
|
*/
|
|
|
|
//set connection string
|
|
PCWSTR connectionString = L"http://localhost:5985";
|
|
|
|
//CREATE SESSION
|
|
DWORD errorCode = WSManCreateSession(apiHandle, connectionString, 0, &creds, NULL, &session);
|
|
if (errorCode != ERROR_SUCCESS)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
//Set timeouts
|
|
WSMAN_DATA timeout;
|
|
timeout.type = WSMAN_DATA_TYPE_DWORD;
|
|
timeout.number = 10000;
|
|
errorCode = WSManSetSessionOption(session, WSMAN_OPTION_TIMEOUTMS_CREATE_SHELL, &timeout);
|
|
if (errorCode != ERROR_SUCCESS)
|
|
{
|
|
return false;
|
|
}
|
|
errorCode = WSManSetSessionOption(session, WSMAN_OPTION_TIMEOUTMS_RUN_SHELL_COMMAND, &timeout);
|
|
if (errorCode != ERROR_SUCCESS)
|
|
{
|
|
return false;
|
|
}
|
|
errorCode = WSManSetSessionOption(session, WSMAN_OPTION_TIMEOUTMS_RECEIVE_SHELL_OUTPUT, &timeout);
|
|
if (errorCode != ERROR_SUCCESS)
|
|
{
|
|
return false;
|
|
}
|
|
errorCode = WSManSetSessionOption(session, WSMAN_OPTION_TIMEOUTMS_SEND_SHELL_INPUT, &timeout);
|
|
if (errorCode != ERROR_SUCCESS)
|
|
{
|
|
return false;
|
|
}
|
|
errorCode = WSManSetSessionOption(session, WSMAN_OPTION_TIMEOUTMS_SIGNAL_SHELL, &timeout);
|
|
if (errorCode != ERROR_SUCCESS)
|
|
{
|
|
return false;
|
|
}
|
|
errorCode = WSManSetSessionOption(session, WSMAN_OPTION_TIMEOUTMS_CLOSE_SHELL, &timeout);
|
|
if (errorCode != ERROR_SUCCESS)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
bool CreateShell()
|
|
{
|
|
WSMAN_SHELL_ASYNC createShellAsync;
|
|
ZeroMemory(&createShellAsync, sizeof(WSMAN_SHELL_ASYNC));
|
|
createShellAsync.operationContext = this;
|
|
createShellAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)ShellCreatedCallback;
|
|
|
|
WSMAN_STREAM_ID_SET stdinSet;
|
|
PCWSTR stdinIds[] = { WSMAN_STREAM_ID_STDIN };
|
|
stdinSet.streamIDsCount = sizeof(stdinIds) / sizeof(PCWSTR);
|
|
stdinSet.streamIDs = stdinIds;
|
|
|
|
stdoutIds[0] = WSMAN_STREAM_ID_STDOUT;
|
|
stdoutIds[1] = WSMAN_STREAM_ID_STDERR;
|
|
stdoutSet.streamIDsCount = sizeof(stdoutIds) / sizeof(PCWSTR);
|
|
stdoutSet.streamIDs = stdoutIds;
|
|
|
|
WSMAN_ENVIRONMENT_VARIABLE vars[] = { { L"var1", L"val1" }, { L"var2", L"val2" }};
|
|
WSMAN_ENVIRONMENT_VARIABLE_SET varSet;
|
|
varSet.varsCount = sizeof(vars)/sizeof(WSMAN_ENVIRONMENT_VARIABLE);
|
|
varSet.vars = vars;
|
|
|
|
WSMAN_SHELL_STARTUP_INFO startupInfo;
|
|
ZeroMemory(&startupInfo, sizeof(startupInfo));
|
|
startupInfo.idleTimeoutMs = idleTimeout;
|
|
startupInfo.inputStreamSet = &stdinSet;
|
|
startupInfo.outputStreamSet = &stdoutSet;
|
|
startupInfo.workingDirectory = L"c:\\";
|
|
startupInfo.variableSet = &varSet;
|
|
startupInfo.name = shellName;
|
|
|
|
WSMAN_DATA inboundData;
|
|
ZeroMemory(&inboundData, sizeof(inboundData));
|
|
inboundData.type = WSMAN_DATA_TYPE_TEXT;
|
|
inboundData.text.buffer = L"<test><test2>hello</test2><test3></test3></test>";
|
|
inboundData.text.bufferLength = wcslen(inboundData.text.buffer);
|
|
|
|
WSManCreateShell(session, 0, shellUri, &startupInfo, NULL, &inboundData, &createShellAsync, &shellHandle);
|
|
|
|
if (shellHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!WaitForSingleObject(shellCreated, INFINITE) == WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool DeleteShell()
|
|
{
|
|
if (shellHandle)
|
|
{
|
|
WSMAN_SHELL_ASYNC deleteShellAsync;
|
|
ZeroMemory(&deleteShellAsync, sizeof(WSMAN_SHELL_ASYNC));
|
|
deleteShellAsync.operationContext = this;
|
|
deleteShellAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)ShellDeletedCallback;
|
|
|
|
WSManCloseShell(shellHandle, 0, &deleteShellAsync);
|
|
|
|
if (WaitForSingleObject(shellDeleted, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
false;
|
|
}
|
|
shellHandle = NULL;
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool DisconnectShell()
|
|
{
|
|
if (shellHandle)
|
|
{
|
|
WSMAN_SHELL_ASYNC disconnectShellAsync;
|
|
ZeroMemory(&disconnectShellAsync, sizeof(WSMAN_SHELL_ASYNC));
|
|
disconnectShellAsync.operationContext = this;
|
|
disconnectShellAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)ShellDisconnectedCallback;
|
|
|
|
WSMAN_SHELL_DISCONNECT_INFO disconnectInfo;
|
|
disconnectInfo.idleTimeoutMs = 3*60*1000;
|
|
WSManDisconnectShell(shellHandle, 0, &disconnectInfo, &disconnectShellAsync);
|
|
|
|
if (WaitForSingleObject(shellDisconnected, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
bool ReconnectShell()
|
|
{
|
|
if (shellHandle)
|
|
{
|
|
WSMAN_SHELL_ASYNC reconnectShellAsync;
|
|
ZeroMemory(&reconnectShellAsync, sizeof(WSMAN_SHELL_ASYNC));
|
|
reconnectShellAsync.operationContext = this;
|
|
reconnectShellAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)ShellReconnectedCallback;
|
|
|
|
WSManReconnectShell(shellHandle, 0, &reconnectShellAsync);
|
|
|
|
if (WaitForSingleObject(shellReconnected, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
}
|
|
return true;
|
|
}
|
|
|
|
bool ConnectShell(PCWSTR shellID)
|
|
{
|
|
WSMAN_SHELL_ASYNC connectShellAsync;
|
|
ZeroMemory(&connectShellAsync, sizeof(WSMAN_SHELL_ASYNC));
|
|
connectShellAsync.operationContext = this;
|
|
connectShellAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)ShellConnectedCallback;
|
|
|
|
WSMAN_DATA inboundData;
|
|
ZeroMemory(&inboundData, sizeof(inboundData));
|
|
inboundData.type = WSMAN_DATA_TYPE_TEXT;
|
|
inboundData.text.buffer = L"<test><test2>hello</test2><test3></test3></test>";
|
|
inboundData.text.bufferLength = wcslen(inboundData.text.buffer);
|
|
|
|
WSManConnectShell(session, 0, shellUri, shellID, NULL, &inboundData, &connectShellAsync, &shellHandle);
|
|
|
|
if (shellHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (WaitForSingleObject(shellConnected, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CreateCommand(PCWSTR command)
|
|
{
|
|
WSMAN_SHELL_ASYNC createCommandAsync;
|
|
ZeroMemory(&createCommandAsync, sizeof(createCommandAsync));
|
|
createCommandAsync.operationContext = this;
|
|
createCommandAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)CommandCreatedCallback;
|
|
|
|
WSManRunShellCommand(shellHandle, 0, command, NULL, NULL, &createCommandAsync, &commandHandle);
|
|
|
|
if (commandHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (WaitForSingleObject(commandCreated, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool ConnectCommand(PCWSTR commandId)
|
|
{
|
|
WSMAN_SHELL_ASYNC connectCommandAsync;
|
|
ZeroMemory(&connectCommandAsync, sizeof(connectCommandAsync));
|
|
connectCommandAsync.operationContext = this;
|
|
connectCommandAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)CommandConnectedCallback;
|
|
|
|
WSMAN_DATA inboundData;
|
|
ZeroMemory(&inboundData, sizeof(inboundData));
|
|
inboundData.type = WSMAN_DATA_TYPE_TEXT;
|
|
inboundData.text.buffer = L"<test><test2>hello</test2><test3></test3></test>";
|
|
inboundData.text.bufferLength = wcslen(inboundData.text.buffer);
|
|
|
|
|
|
WSManConnectShellCommand(shellHandle, 0, commandId, NULL, &inboundData, &connectCommandAsync, &commandHandle);
|
|
|
|
if (commandHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (WaitForSingleObject(commandConnected, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool DeleteCommand(DWORD expectedError)
|
|
{
|
|
if (commandHandle)
|
|
{
|
|
WSMAN_SHELL_ASYNC deleteCommandAsync;
|
|
ZeroMemory(&deleteCommandAsync, sizeof(deleteCommandAsync));
|
|
deleteCommandAsync.operationContext = this;
|
|
deleteCommandAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)CommandDeletedCallback;
|
|
|
|
WSManCloseCommand(commandHandle, 0, &deleteCommandAsync);
|
|
|
|
if (WaitForSingleObject(commandDeleted, INFINITE) == WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
commandHandle = NULL;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool Signal(PCWSTR signalURL)
|
|
{
|
|
WSMAN_SHELL_ASYNC signalAsync;
|
|
ZeroMemory(&signalAsync, sizeof(signalAsync));
|
|
signalAsync.operationContext = this;
|
|
signalAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)SignalCallback;
|
|
|
|
WSManSignalShell(shellHandle, commandHandle, 0, signalURL, &signalAsync, &signalHandle);
|
|
|
|
if (signalHandle == NULL)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (WaitForSingleObject(signal, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool CloseSignal(DWORD expectedError)
|
|
{
|
|
if (signalHandle)
|
|
{
|
|
if (!WSManCloseOperation(signalHandle, 0))
|
|
{
|
|
return false;
|
|
}
|
|
signalHandle = NULL;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool QueueReceive()
|
|
{
|
|
WSMAN_SHELL_ASYNC receiveAsync;
|
|
ZeroMemory(&receiveAsync, sizeof(receiveAsync));
|
|
receiveAsync.operationContext = this;
|
|
receiveAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)ReceiveCallback;
|
|
|
|
WSManReceiveShellOutput(shellHandle, commandHandle, 0, &stdoutSet, &receiveAsync, &receiveHandle);
|
|
if (NULL == receiveHandle)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
bool WaitAndCloseReceive()
|
|
{
|
|
//wait for receive operation to complete
|
|
if (WaitForSingleObject(receive, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!WSManCloseOperation(receiveHandle, 0))
|
|
{
|
|
return false;
|
|
}
|
|
receiveHandle = NULL;
|
|
return true;
|
|
}
|
|
|
|
bool Send(PCWSTR stream, WSMAN_DATA *streamData, BOOL endOfStream)
|
|
{
|
|
WSMAN_SHELL_ASYNC sendAsync;
|
|
ZeroMemory(&sendAsync, sizeof(sendAsync));
|
|
sendAsync.operationContext = this;
|
|
sendAsync.completionFunction = (WSMAN_SHELL_COMPLETION_FUNCTION)SendCallback;
|
|
|
|
WSManSendShellInput(shellHandle, commandHandle, 0, stream, streamData, endOfStream, &sendAsync, &sendHandle);
|
|
if (NULL == sendHandle)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (WaitForSingleObject(send, INFINITE) != WAIT_OBJECT_0)
|
|
{
|
|
return false;
|
|
}
|
|
|
|
if (!WSManCloseOperation(sendHandle, 0))
|
|
{
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
|
|
static VOID ShellCreatedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->shellCreatedError = error->code;
|
|
pThis->shellCreatedCount++;
|
|
SetEvent(pThis->shellCreated);
|
|
}
|
|
|
|
static VOID ShellDeletedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->shellDeletedError = error->code;
|
|
pThis->shellDeletedCount++;
|
|
SetEvent(pThis->shellDeleted);
|
|
}
|
|
|
|
static VOID ShellDisconnectedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->shellDisconnectedError = error->code;
|
|
pThis->shellDisconnectedCount++;
|
|
SetEvent(pThis->shellDisconnected);
|
|
}
|
|
|
|
static VOID ShellReconnectedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->shellReconnectedError = error->code;
|
|
pThis->shellReconnectedCount++;
|
|
SetEvent(pThis->shellReconnected);
|
|
}
|
|
|
|
static VOID ShellConnectedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->shellConnectedError = error->code;
|
|
pThis->shellConnectedCount++;
|
|
SetEvent(pThis->shellConnected);
|
|
}
|
|
|
|
static VOID CommandCreatedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->commandCreatedError = error->code;
|
|
pThis->commandCreatedCount++;
|
|
SetEvent(pThis->commandCreated);
|
|
}
|
|
|
|
static VOID CommandDeletedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->commandDeletedError = error->code;
|
|
pThis->commandDeletedCount++;
|
|
SetEvent(pThis->commandDeleted);
|
|
}
|
|
|
|
static VOID CommandConnectedCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->commandConnectedError = error->code;
|
|
pThis->commandConnectedCount++;
|
|
SetEvent(pThis->commandConnected);
|
|
}
|
|
|
|
static VOID SignalCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->signalError = error->code;
|
|
pThis->signalCount++;
|
|
SetEvent(pThis->signal);
|
|
}
|
|
|
|
static VOID ReceiveCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->receiveError = error->code;
|
|
pThis->receiveCount++;
|
|
if(data)
|
|
{
|
|
WSMAN_RECEIVE_DATA_RESULT* receivedata = &(data->receiveData);
|
|
//TASSERT(receivedata->streamData.type == WSMAN_DATA_TYPE_BINARY, L"receive binary data");
|
|
if (pThis->receiveByteCount + receivedata->streamData.binaryData.dataLength < 1024) //receiveBuffer is max 1024 in size
|
|
{
|
|
memcpy(pThis->receiveBuffer + pThis->receiveByteCount, receivedata->streamData.binaryData.data, receivedata->streamData.binaryData.dataLength);
|
|
pThis->receiveByteCount += receivedata->streamData.binaryData.dataLength;
|
|
}
|
|
}
|
|
if (flags & WSMAN_FLAG_CALLBACK_END_OF_STREAM)
|
|
{
|
|
pThis->receiveEndOfStreamCount++;
|
|
}
|
|
if ((flags & WSMAN_FLAG_CALLBACK_END_OF_OPERATION) ||
|
|
(pThis->receiveSignalEveryResult))
|
|
{
|
|
SetEvent(pThis->receive);
|
|
}
|
|
}
|
|
|
|
static VOID SendCallback(
|
|
_In_ PVOID operationContext, //user defined context
|
|
DWORD flags, // one or more flags from WSManCallbackFlags
|
|
_In_ WSMAN_ERROR *error, // error allocated and owned by the winrm stack; valid in the callback only;
|
|
_In_ WSMAN_SHELL_HANDLE shell, // shell handle associated with the user context
|
|
_In_opt_ WSMAN_COMMAND_HANDLE command, // command handle associated with the user context
|
|
_In_opt_ WSMAN_OPERATION_HANDLE operationHandle, // valid only for Send/Receive/Signal operations; must be closed using WSManCloseOperation
|
|
_In_opt_ WSMAN_RESPONSE_DATA *data // output data from command/shell; allocated internally and owned by the winrm stack
|
|
// valid only within this function
|
|
)
|
|
{
|
|
ShellClient *pThis = (ShellClient*) operationContext;
|
|
pThis->sendError = error->code;
|
|
pThis->sendCount++;
|
|
SetEvent(pThis->send);
|
|
}
|
|
|
|
WSMAN_SHELL_HANDLE shellHandle;
|
|
HANDLE shellCreated;
|
|
DWORD shellCreatedCount;
|
|
DWORD shellCreatedError;
|
|
|
|
HANDLE shellDeleted;
|
|
DWORD shellDeletedCount;
|
|
DWORD shellDeletedError;
|
|
|
|
HANDLE shellDisconnected;
|
|
DWORD shellDisconnectedCount;
|
|
DWORD shellDisconnectedError;
|
|
|
|
HANDLE shellReconnected;
|
|
DWORD shellReconnectedCount;
|
|
DWORD shellReconnectedError;
|
|
|
|
HANDLE shellConnected;
|
|
DWORD shellConnectedCount;
|
|
DWORD shellConnectedError;
|
|
|
|
WSMAN_COMMAND_HANDLE commandHandle;
|
|
HANDLE commandCreated;
|
|
DWORD commandCreatedCount;
|
|
DWORD commandCreatedError;
|
|
|
|
HANDLE commandDeleted;
|
|
DWORD commandDeletedCount;
|
|
DWORD commandDeletedError;
|
|
|
|
HANDLE commandConnected;
|
|
DWORD commandConnectedCount;
|
|
DWORD commandConnectedError;
|
|
|
|
WSMAN_OPERATION_HANDLE signalHandle;
|
|
HANDLE signal;
|
|
DWORD signalCount;
|
|
DWORD signalError;
|
|
|
|
WSMAN_OPERATION_HANDLE receiveHandle;
|
|
HANDLE receive;
|
|
DWORD receiveCount;
|
|
DWORD receiveError;
|
|
bool receiveEndOfStreamCount;
|
|
bool receiveSignalEveryResult;
|
|
BYTE receiveBuffer[1024];
|
|
DWORD receiveByteCount;
|
|
|
|
WSMAN_OPERATION_HANDLE sendHandle;
|
|
HANDLE send;
|
|
DWORD sendCount;
|
|
DWORD sendError;
|
|
|
|
WSMAN_API_HANDLE apiHandle;
|
|
WSMAN_SESSION_HANDLE session;
|
|
DWORD idleTimeout;
|
|
PCWSTR shellUri;
|
|
WSMAN_STREAM_ID_SET stdoutSet;
|
|
PCWSTR stdoutIds[2];
|
|
PCWSTR shellName;
|
|
};
|
|
|
|
|