2025-11-28 00:35:46 +09:00

504 lines
23 KiB
C

//
// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright (c) Microsoft Corporation. All rights reserved
//
#include <windows.h>
#include <mi.h>
#include "utilities.h"
#include "operations.h"
/* Do_Operation() gets user to select the operation and calls into a function to carry it out. */
void Do_Operation(MI_Application *miApplication, _In_opt_z_ const wchar_t *computerName, _In_opt_z_ const wchar_t *protocol, _In_z_ const wchar_t *namespaceName, const wchar_t *className)
{
MI_Session miSession = MI_SESSION_NULL;
MI_Result miResult = MI_RESULT_OK;
wchar_t selection;
/* Create a session to against the specified computer name. NULL means local and uses WMI-DCOM by default,
* or when name is specified will use WS-Man protcol by default.
* The session must be closed via a call to MI_Session_Close().
*/
miResult = MI_Application_NewSession(miApplication, protocol, computerName, NULL, NULL, NULL, &miSession);
if (miResult != MI_RESULT_OK)
{
/* This API is likely to fail with invalid parameter or out of memory errors. */
wprintf(L"MI_Application_NewSession failed, error = %s\n", MI_Result_To_String(miResult));
goto noSessionError;
}
do
{
/* Helper API to retrieve the operation selection */
selection = GetUserSelection(
L"Which type of operation do you want to run?\n"
L"\t[1] Instance Get\n"
L"\t[2] Instance Create\n"
L"\t[3] Instance Delete\n"
L"\t[4] Instance Modify\n"
L"\t[5] Instance Enumerate\n"
L"\t[6] Instance Query\n"
L"\t[7] Instance Association\n"
L"\t[8] Instance Reference\n"
L"\t[9] Instance Method\n"
L"\t[A] Indication Subscriptions\n"
L"\t[0] back to options\n",
L"0123456789a");
switch(selection)
{
case L'1':
Do_Get(&miSession, namespaceName, className);
break;
case L'2':
Do_Create(&miSession, namespaceName, className);
break;
case L'3':
Do_Delete(&miSession, namespaceName, className);
break;
case L'4':
Do_Modify(&miSession, namespaceName, className);
break;
case L'5':
Do_Enumerate(&miSession, namespaceName, className);
break;
case L'6':
Do_Query(&miSession, namespaceName);
break;
case L'7':
Do_Association(&miSession, namespaceName, className);
break;
case L'8':
Do_Reference(&miSession, namespaceName, className);
break;
case L'9':
Do_Method(&miSession, namespaceName, className);
break;
case L'a':
Do_Subscribe(&miSession, namespaceName);
break;
}
} while (selection != L'0' && miResult == MI_RESULT_OK);
miResult = MI_Session_Close(&miSession, NULL, NULL);
if (miResult != MI_RESULT_OK)
{
/* This API is likely to fail with invalid parameter, out of memory errors or access denied.
* When an out of memory error happens, the session will shut down as best it can.
* Invalid parameter means a programming error happened.
* Access denied means the security context while calling into the Close() is different from
* when the session was created. This will be a programming error and could happen if closing
* from a different thread and forgetting to impersonate.
*/
wprintf(L"MI_Session_Close failed, error = %s\n", MI_Result_To_String(miResult));
goto noSessionError;
}
noSessionError:
return;
}
/* InstanceResultCallback() is a callback function for all asynchronous instance operation results. */
void MI_CALL InstanceResultCallback(
_In_opt_ MI_Operation *miOperation,
_In_ void *callbackContext,
_In_opt_ const MI_Instance *miInstance,
MI_Boolean moreResults,
_In_ MI_Result miResult,
_In_opt_z_ const MI_Char *errorString,
_In_opt_ const MI_Instance *errorDetails,
_In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
{
struct InstanceResultCallback_Context *actualContext = (struct InstanceResultCallback_Context*) callbackContext;
if (miInstance)
{
/* If we have an instance it implies the operation was successful. We will dump the instance
* to the screen.
*/
wprintf(L"------------------------------------------\n");
Dump_MI_Instance(miInstance, actualContext->keysOnly, 0);
actualContext->numberInstances ++;
}
if (moreResults == MI_FALSE)
{
MI_Result _miResult; /* temporary internal result */
/* This state means the callback will not be called again as there are no more results.
* We can cleanup the operation objects and, if necessary, notify the caller that
* the operation is finished.
*/
wprintf(L"------------------------------------------\n");
if (miResult != MI_RESULT_OK)
{
/* Operation failed, we we will dump all the error information we have. */
wprintf(L"Operation failed, MI_Result=%s, errorString=%s, errorDetails=\n", MI_Result_To_String(miResult), errorString);
Dump_MI_Instance(errorDetails, MI_FALSE, 0);
}
else
{
/* Succeeded, so we will dump the final instance count. */
wprintf(L"Operation succeeded, number of instances=%u\n", actualContext->numberInstances);
}
wprintf(L"------------------------------------------\n");
if (resultAcknowledgement)
{
/* By default an Auto-acknowledgement is requested with the operation, which means that any
* result data is only valid in this asyncronous callback, and will be deleted then the
* callback returns.
* Manual acknowlegement allows the result data to be queued to a different thread for processing if needed, and
* when finished with can be acknowledged in this way. No new results will be delivered until the data is
* acknowledged.
* Do not take too long to process the data though as the server may give up on the operation and cancel it.
*/
MI_Result _miResult;
_miResult = resultAcknowledgement(miOperation);
if (_miResult != MI_RESULT_OK)
{
/* Failure to acknowledge happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"Instance acknowledgement callback failed, error %s\n", MI_Result_To_String(_miResult));
}
}
/* This operation is asynchronous, to the operation will close asynchronously. */
if (miOperation != NULL)
{
_miResult = MI_Operation_Close(miOperation);
if (_miResult != MI_RESULT_OK)
{
/* Failure to close operation happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"MI_Operation_Close failed, error = %s\n", MI_Result_To_String(_miResult));
}
}
actualContext->finalResult = miResult;
/* Notify the main waiting thread we are done.
* The way this sample uses asynchronous instance operations it would actually be better to
* to use the synchronous APIs as they may be a little more efficient. If this was a service
* it is possible that everything could be very asynchronous in nature with no real need for a
* waiting thread.
*/
SetEvent(actualContext->asyncNotificationHandle);
}
else
{
if (resultAcknowledgement)
{
/* By default an Auto-acknowledgement is requested with the operation, which means that any
* result data is only valid in this asyncronous callback, and will be deleted then the
* callback returns.
* Manual acknowlegement allows the result data to be queued to a different thread for processing if needed, and
* when finished with can be acknowledged in this way. No new results will be delivered until the data is
* acknowledged.
* Do not take too long to process the data though as the server may give up on the operation and cancel it.
*/
MI_Result _miResult;
_miResult = resultAcknowledgement(miOperation);
if (_miResult != MI_RESULT_OK)
{
/* Failure to acknowledge happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"Instance acknowledgement callback failed, error %s\n", MI_Result_To_String(_miResult));
}
}
}
}
/* IndicationResultCallback() is a callback function for all asynchronous subscribe operation results. */
void MI_CALL IndicationResultCallback(
_In_opt_ MI_Operation *miOperation,
_In_ void *callbackContext,
_In_opt_ const MI_Instance *miInstance,
_In_opt_z_ const MI_Char *bookmark,
_In_opt_z_ const MI_Char *machineID,
MI_Boolean moreResults,
_In_ MI_Result miResult,
_In_opt_z_ const MI_Char *errorString,
_In_opt_ const MI_Instance *errorDetails,
_In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
{
struct InstanceResultCallback_Context *actualContext = (struct InstanceResultCallback_Context*) callbackContext;
if (miInstance)
{
/* If we have an instance it implies the operation was successful. We will dump the instance
* to the screen.
*/
wprintf(L"------------------------------------------\n");
Dump_MI_Instance(miInstance, actualContext->keysOnly, 0);
actualContext->numberInstances ++;
}
if (moreResults == MI_FALSE)
{
MI_Result _miResult; /* temporary internal result */
/* This state means the callback will not be called again as there are no more results.
* We can cleanup the operation objects and, if necessary, notify the caller that
* the operation is finished.
*/
wprintf(L"------------------------------------------\n");
if (actualContext->numberInstances == 0 && miResult != MI_RESULT_OK)
{
/* Operation failed, we we will dump all the error information we have. */
wprintf(L"Operation failed, MI_Result=%s, errorString=%s, errorDetails=\n", MI_Result_To_String(miResult), errorString);
Dump_MI_Instance(errorDetails, MI_FALSE, 0);
}
else
{
/* Succeeded, so we will dump the final instance count. */
wprintf(L"Operation succeeded, number of instances=%u\n", actualContext->numberInstances);
}
wprintf(L"------------------------------------------\n");
if (resultAcknowledgement)
{
/* By default an Auto-acknowledgement is requested with the operation, which means that any
* result data is only valid in this asyncronous callback, and will be deleted then the
* callback returns.
* Manual acknowlegement allows the result data to be queued to a different thread for processing if needed, and
* when finished with can be acknowledged in this way. No new results will be delivered until the data is
* acknowledged.
* Do not take too long to process the data though as the server may give up on the operation and cancel it.
*/
MI_Result _miResult;
_miResult = resultAcknowledgement(miOperation);
if (_miResult != MI_RESULT_OK)
{
/* Failure to acknowledge happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"indication acknowledgement callback failed, error %s\n", MI_Result_To_String(_miResult));
}
}
/* This operation is asynchronous, to the operation will close asynchronously. */
if (miOperation != NULL)
{
_miResult = MI_Operation_Close(miOperation);
if (_miResult != MI_RESULT_OK)
{
/* Failure to close operation happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"MI_Operation_Close failed, error = %s\n", MI_Result_To_String(_miResult));
}
}
actualContext->finalResult = miResult;
}
else
{
if (resultAcknowledgement)
{
/* By default an Auto-acknowledgement is requested with the operation, which means that any
* result data is only valid in this asyncronous callback, and will be deleted then the
* callback returns.
* Manual acknowlegement allows the result data to be queued to a different thread for processing if needed, and
* when finished with can be acknowledged in this way. No new results will be delivered until the data is
* acknowledged.
* Do not take too long to process the data though as the server may give up on the operation and cancel it.
*/
MI_Result _miResult;
_miResult = resultAcknowledgement(miOperation);
if (_miResult != MI_RESULT_OK)
{
/* Failure to acknowledge happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"indication acknowledgement callback failed, error %s\n", MI_Result_To_String(_miResult));
}
}
/* Just a reminder message to the user of how to close the operation. */
wprintf(L"Press [0] to end subscription\n");
}
/* Bookmarks and machine IDs are not covered in this sample. */
MI_UNREFERENCED_PARAMETER(bookmark);
MI_UNREFERENCED_PARAMETER(machineID);
}
/* StreamedResultCallback() is a callback function for method operations that use streamed out parameters.
* A method out parameter needs to be marked with a [stream] qualifier for this callback to be called.
* The callback may be called multiple times for a streamed parameter.
*/
void MI_CALL StreamedResultCallback(
_In_ MI_Operation *operation,
_In_ void *callbackContext,
_In_z_ const MI_Char *parameterName,
_In_ MI_Type resultType,
_In_ const MI_Value *result,
_In_opt_ MI_Result (MI_CALL * resultAcknowledgement)(_In_ MI_Operation *operation))
{
MI_UNREFERENCED_PARAMETER(callbackContext);
/* Print the parameter results. */
wprintf(L"Streamed result callback\n");
Print_Element(parameterName, result, resultType, 0, 0);
if (resultAcknowledgement)
{
/* By default an Auto-acknowledgement is requested with the operation, which means that any
* result data is only valid in this asyncronous callback, and will be deleted then the
* callback returns.
* Manual acknowlegement allows the result data to be queued to a different thread for processing if needed, and
* when finished with can be acknowledged in this way. No new results will be delivered until the data is
* acknowledged.
* Do not take too long to process the data though as the server may give up on the operation and cancel it.
*/
MI_Result miResult;
miResult = resultAcknowledgement(operation);
if (miResult != MI_RESULT_OK)
{
/* Failure to acknowledge happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"Streamed acknowledge callback failed, error %s\n", MI_Result_To_String(miResult));
}
}
}
/* WriteProgressCallback() is a callback function used to report operation progress from the provider. */
void MI_CALL WriteProgressCallback(
_In_ MI_Operation *operation,
_In_opt_ void *callbackContext,
_In_z_ const MI_Char *activity,
_In_z_ const MI_Char *currentOperation,
_In_z_ const MI_Char *statusDescription,
MI_Uint32 percentageComplete,
MI_Uint32 secondsRemaining)
{
MI_UNREFERENCED_PARAMETER(operation);
MI_UNREFERENCED_PARAMETER(callbackContext);
wprintf(L"Progress indicator callback. \nActivity: %s\nCurrent operation: %s\nStatus description: %s\nPercentage complete: %u\nSeconds remaining: %u\n",
activity, currentOperation, statusDescription, percentageComplete, secondsRemaining);
}
/* WriteMessageCallback() is a callback function used to report messages from the provider during an operation. */
void MI_CALL WriteMessageCallback(
_In_ MI_Operation *operation,
_In_opt_ void *callbackContext,
MI_Uint32 channel,
_In_z_ const MI_Char *message)
{
MI_UNREFERENCED_PARAMETER(operation);
MI_UNREFERENCED_PARAMETER(callbackContext);
if (channel == MI_WRITEMESSAGE_CHANNEL_WARNING)
{
wprintf(L"Write message callback (warning): %s\n", message);
}
else if (channel == MI_WRITEMESSAGE_CHANNEL_VERBOSE)
{
wprintf(L"Write message callback (verbose): %s\n", message);
}
else if (channel == MI_WRITEMESSAGE_CHANNEL_DEBUG)
{
wprintf(L"Write message callback (debug): %s\n", message);
}
else
{
wprintf(L"Write message callback (%u): %s\n", channel, message);
}
}
/* WriteErrorCallback() is a callback function used to report non-terminating errors from the provider during an operation, with
* an option (configurable) to report back to the provider to continue or terminate the operation. */
void MI_CALL WriteErrorCallback(
_In_ MI_Operation *operation,
_In_opt_ void *callbackContext,
_In_ MI_Instance*instance,
_In_opt_ MI_Result (MI_CALL * writeErrorResult)(_In_ MI_Operation *operation,
MI_OperationCallback_ResponseType response))
{
MI_UNREFERENCED_PARAMETER(callbackContext);
wprintf(L"Write error callback\n");
Dump_MI_Instance(instance, MI_FALSE, 0);
if (writeErrorResult)
{
MI_Result miResult;
MI_Char selection;
selection = GetUserSelection(L"[1] No"
L"[2] Yes"
L"[3] No to all"
L"[4] Yes to all",
L"1234");
miResult = writeErrorResult(operation, (MI_OperationCallback_ResponseType) (L'1' - selection));
if (miResult != MI_RESULT_OK)
{
/* Failure to acknowledge happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"Write error response callback failed, error %s\n", MI_Result_To_String(miResult));
}
}
}
/* PromptUserCallback() is a callback function used to prompt the user if they want to continue with an operation. */
void MI_CALL PromptUserCallback(
_In_ MI_Operation *operation,
_In_opt_ void *callbackContext,
_In_z_ const MI_Char *message,
MI_PromptType promptType,
_In_opt_ MI_Result (MI_CALL * promptUserResult)(_In_ MI_Operation *operation,
MI_OperationCallback_ResponseType response))
{
MI_UNREFERENCED_PARAMETER(callbackContext);
wprintf(L"Prompt user callback (%s): %s\n", promptType==MI_PROMPTTYPE_NORMAL?L"Normal":L"Critical", message);
if (promptUserResult)
{
MI_Result miResult;
MI_Char selection;
selection = GetUserSelection(L"[1] No"
L"[2] Yes"
L"[3] No to all"
L"[4] Yes to all",
L"1234");
miResult = promptUserResult(operation, (MI_OperationCallback_ResponseType) (L'1' - selection));
if (miResult != MI_RESULT_OK)
{
/* Failure to acknowledge happens as a result of invalid operation handle, out of memory,
* or access denied. Access denied can happen if the identity used to create the session and operation
* is different to that being used to close the operation. For the callback, this is handled by
* the MI infrastructure.
*/
wprintf(L"prompt user response callback failed, error %s\n", MI_Result_To_String(miResult));
}
}
}