Introduction to the SMS 2003 Management Point (MP) API

The MP API was introduced in the second release of the SMS SDK (we are currently in the fourth release, version 3.1). This API is very powerful and can be used to submit discovery, inventory, status, and metering data from a SMS or non-SMS client. It can also be used to request information from an MP, like policies or the location of a distribution point based on an IP subnet or AD site. 

This example shows how to submit a location request to an MP via the MP API. This can be useful for a non-SMS client to be able to find out where to install an SMS package from. A common scenario would be a new install of the OS (maybe right after an image is applied). You could use the MP API to find out where to install the software needed on the image in order to get the machine up to a baseline. I created a win32 console application in Visual Studio and checked the box to add MFC support. For this application to work the smsmsgapi.dll must be registered on the machine (regsvr32 smsmsgapi.dll). Also, make sure smsmsgapi.h and smsmsgapi_i.c are in your project folder. All of these files are included in the SMS SDK.

 

 // LocationRequest.cpp : Defines the entry point for the console application.
// Example of how to submit a location request using the MP API

#include "stdafx.h"
#include "LocationRequest.h"
#include "SmsMsgAPI.h"
#include "SmsMsgAPI_i.c"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

CWinApp theApp;

using namespace std;

//  Macros to perform error handling and make the code cleaner.
#define _BEGIN \
    HRESULT __hrRetVal = S_OK; \
    { \
 
#define _END \
    } \
    __End: \
 
#define _RETVAL __hrRetVal
 
#define _CHECKHR(expr) if(FAILED(expr)) { __hrRetVal=expr; goto __End; }

//Main
int _tmain(int argc, TCHAR* argv[], TCHAR* envp[])
{
    int nRetCode = 0;

    // initialize MFC and print and error on failure
    if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
    {
        _tprintf(_T("Fatal Error: MFC initialization failed\n"));
        nRetCode = 1;
    }
    else
    {
        if(argc < 4)
        {
            printf("Usage:LocationRequest.exe <https://mpname> <CliSubnet> <CliIP> <PkgID> <ADSite>\n");
        }
        else
        {
            CString sMPIP, sClientSubnet, sClientIP, sPackageID, sADSite;
            ISmsMessaging               *pMessaging = NULL;
            ISmsMessage                 *pRequest = NULL;
            ISmsMessage                 *pReply = NULL;
            WCHAR                       *pszRequestMessage = NULL;
            WCHAR                       *pszReplyMessage = NULL;
            CString                        sNewLocationRequest;
            BSTR                        sLocationRequest = NULL;
            BSTR                        sMPIPAddress;

            //Get command line arguments
            sMPIP = argv[1];
            sClientSubnet = argv[2];
            sClientIP = argv[3];
            sPackageID = argv[4];
            sADSite = argv[5];

            //Format XML based Location Request
            sNewLocationRequest = "<ContentLocationRequest SchemaVersion=\"1.0\"> \n \
<Package ID=\"" + sPackageID + "\" Version=\"*\"/> \n \
<AssignedSite SiteCode=\"*\"/> \n \
<ClientLocationInfo> \n \
<ADSite Name=\"" + sADSite + "\"/> \n \
<IPAddresses> \n \
<IPAddress SubnetAddress=\"" + sClientSubnet + "\" Address=\"" + sClientIP + "\"/> \n \
</IPAddresses> \n \
</ClientLocationInfo> \n \
</ContentLocationRequest>";

            printf("\nLocation Request:\n%s",sNewLocationRequest);  //Print request to command line

            sLocationRequest = sNewLocationRequest.AllocSysString();
            sMPIPAddress = sMPIP.AllocSysString();
            CoInitialize(0);

        _BEGIN

            //Create root messaging object
            _CHECKHR( ::CoCreateInstance(
                        CLSID_SmsMessaging,
                        NULL,
                        CLSCTX_INPROC,
                        IID_ISmsMessaging,
                        (LPVOID*)&pMessaging) );

            //Create message object for request
            _CHECKHR( pMessaging->CreateMessage(&pRequest) );

            //Set the target of the message to the Location Manager endpoint
            _CHECKHR( pRequest->SetTargetEndpoint(L"MP_LocationManager") );

            //Set the message body with the request
            _CHECKHR( pRequest->SetBodyFromString(sLocationRequest) );

            // Invoke the targeted endpoint on the local machine with the request,
            // and retrieve the reply.
            _CHECKHR( pMessaging->Invoke(sMPIPAddress, pRequest, &pReply) );

            // Extract body from reply message.
            _CHECKHR( pReply->GetBodyToString(&pszReplyMessage) );

            wprintf(L"\n\nReply from MP:\n%s", (wchar_t *) pszReplyMessage);

        _END

            printf("\n\n%s%X", "Return Code=", __hrRetVal);

            if(pszReplyMessage)
            {
                ::CoTaskMemFree(pszReplyMessage);
            }
            if(pReply)
            {
                pReply->Release();
            }
            if(pszRequestMessage)
            {
                ::CoTaskMemFree(pszRequestMessage);
            }
            if(pRequest)
            {
                pRequest->Release();
            }
            if(pMessaging)
            {
                pMessaging->Release();
            }
        }
    }
    return nRetCode;
}