Submitting software inventory records to an SMS 2003 MP using the MP API

There are several supported ways to add data to the SMS database but they typically come from an SMS 2003 advanced client. If you want to add data to an existing client without having to make the agent on the client send it up, or add data to the database for a non-SMS client, then you can use the MP API.

The SMS SDK contains documentation and some sample code for submitting data via the MP API. There are some other things you'll need to do in order to get the MP API working with SMS 2003 SP1 and above.

Below is an example of using the MP API to submit software inventory data to a Management Point. This data gets converted from XML to a SIC by the MP, then moved to the site server, and finally loaded into the database. Keep in mind that the software inventory data I'm loading into the database in this example is the minimum so much more can be added. Also, you can create your own GUIDs using CoCreateGUID().

Here are some tips when developing/testing submitting discovery data using the MP API.
- Enable verbose and debug logging on the SMS 2003 Management Point you're working with.
- Have an SMS 2003 advanced client already submitting data to this MP.
- Turn on report archival on the advanced client so you can see what a properly formatted XML looks like.
- View the following logs in this order: IIS logs (shows IIS handling the message), ccmisapi.log (SMS ISAPI filter), MP_Sinv.log (converts the XML to a SIC), mpfdm.log (moves the SIC from the MP to site server), and sinvproc.log (loads the SIC into the database).
- Make sure you've installed the hotfix from KB917873 onto your SDK. This article is not published as of 07/03/2006 but the hotfix is still available by calling Microsoft support.
- Don't forget to set the Byte Order Mark in your XML attachment.
- Make sure you call SetClientID, which is only usable if you've included the .h/.c files from KB917873 in your project.
- If the program fails when running on the MP with https:// in front of the MP Name, try running it without the https:// (this goes through COM instead of IIS).
- Run the DDRExample program first to create a discovery record in the database prior to using this application

 //MPAPI-SinvExample.cpp : Defines the entry point for the console application.
//Rslaten 07/2006

#include "stdafx.h"
#include "MPAPI-SinvExample.h"
#include "SmsMsgAPI.h"
#include "SmsMsgAPI_i.c"
#include "strsafe.h"
#ifdef _DEBUG
#define new DEBUG_NEW
#endif

#define MAX_BUFFER_LENGTH 0x1000

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; }

int wmain( int argc, wchar_t *argv[], wchar_t *envp[] )
{
  int nRetCode = 0;

  // initialize MFC and print and error on failure
   if (!AfxWinInit(::GetModuleHandle(NULL), NULL, ::GetCommandLine(), 0))
 {
       // TODO: change error code to suit your needs
      _tprintf(_T("Fatal Error: MFC initialization failed\n"));
       nRetCode = 1;
   }
   else
   {
       if (argc < 2)
       {
           printf("Usage:MPAPI-HinvExample.exe <https://mpname>\n");
       }
       else
       {
           static WCHAR SINVBody[MAX_BUFFER_LENGTH];
          static WCHAR SINVAttach[MAX_BUFFER_LENGTH];
            ISmsMessaging               *pMessaging = NULL;
         ISmsMessage                 *pRequest = NULL;
           ISmsMessage                 *pReply = NULL;
         ISmsMessage2                *pRequest2 = NULL;
          WCHAR                       *pszRequestMessage = NULL;
          WCHAR                       *pszReplyMessage = NULL;
            WCHAR                       *sMPName = NULL;
            WCHAR                       *pszTrackingID = NULL;
          LPCWSTR                     sClientID = NULL;
           LPCWSTR                     sReportID = NULL;
           LPCWSTR                     sEndPoint = NULL;

           //Set variables
            sReportID = L"{00000000-0000-0000-0000-000000000002}";
          sEndPoint = L"MP_SinvEndpoint";
         sClientID = L"GUID:8081C07C-4674-48E4-A525-5CAD419A4EB3";
           sMPName = argv[1];

          CoInitialize(NULL);

         //Build Report Header for Hinv
                   wcscat(SINVBody,L"<ReportHeader>");
                   wcscat(SINVBody,L"<Identification>");
                   wcscat(SINVBody,L"<Machine>");
                   wcscat(SINVBody,L"<ClientID>GUID:8081C07C-4674-48E4-A525-5CAD419A4EB3</ClientID>");
                   wcscat(SINVBody,L"</Machine>");
                   wcscat(SINVBody,L"</Identification>");
                   wcscat(SINVBody,L"</ReportHeader>");
          //Build Message Attachment for Hinv
                   SINVAttach[0] = 0xFEFF; //Add BOM
                   wcscat(SINVAttach,L"<Report>");
                   wcscat(SINVAttach,L"<ReportHeader>");
                   wcscat(SINVAttach,L"<Identification>");
                   wcscat(SINVAttach,L"<Machine>");
                   wcscat(SINVAttach,L"<ClientInstalled>1</ClientInstalled>");
                   wcscat(SINVAttach,L"<ClientType>1</ClientType>");
                   wcscat(SINVAttach,L"<ClientID>GUID:8081C07C-4674-48E4-A525-5CAD419A4EB3</ClientID>");
                   wcscat(SINVAttach,L"<ClientVersion>1.0</ClientVersion>");
                   wcscat(SINVAttach,L"<NetBIOSName>MPAPITestClient</NetBIOSName>");
                   wcscat(SINVAttach,L"<CodePage>437</CodePage>");
                   wcscat(SINVAttach,L"<SystemDefaultLCID>1033</SystemDefaultLCID>");
                   wcscat(SINVAttach,L"</Machine>");
                   wcscat(SINVAttach,L"</Identification>");
                   wcscat(SINVAttach,L"<ReportDetails>");
                   wcscat(SINVAttach,L"<ReportContent>Inventory\\x0020Data</ReportContent>");
                   wcscat(SINVAttach,L"<ReportType>Full</ReportType>");
                   wcscat(SINVAttach,L"<Date>20060120124946.000000-360</Date>");
                   wcscat(SINVAttach,L"<Version>1.3</Version>");
                   wcscat(SINVAttach,L"<Format>1.0</Format>");
                   wcscat(SINVAttach,L"</ReportDetails>");
                   wcscat(SINVAttach,L"<InventoryAction ActionType=\"Predefined\">");
    wcscat(SINVAttach,L"<InventoryActionID>{00000000-0000-0000-0000-000000000002}</InventoryActionID>");
                   wcscat(SINVAttach,L"<Description>Software</Description>");
    wcscat(SINVAttach,L"<InventoryActionLastUpdateTime>20050913162140.000000+000</InventoryActionLastUpdateTime>");
                   wcscat(SINVAttach,L"</InventoryAction>");
                   wcscat(SINVAttach,L"</ReportHeader>");
                   wcscat(SINVAttach,L"<ReportBody>");
                   wcscat(SINVAttach,L"<Instance ParentClass=\"FileSystemFile\" Class=\"FileSystemFile\"");
                   wcscat(SINVAttach,L" Namespace=\"\\\\MPAPITestClient\\ROOT\\ccm\\invagt\\\" Content=\"New\">");
                   wcscat(SINVAttach,L"<FileSystemFile>");
                   wcscat(SINVAttach,L"<CompanyName>Microsoft\\x0020Corporation</CompanyName>");
                   wcscat(SINVAttach,L"<FileDescription>Notepad</FileDescription>");
                   wcscat(SINVAttach,L"<FileVersion>5.1.2600.2180\\x0020(xpsp_sp2_rtm.040803-2158)</FileVersion>");
                   wcscat(SINVAttach,L"<LastWriteDate>20040804060000.000000+***</LastWriteDate>");
                   wcscat(SINVAttach,L"<Name>notepad.exe</Name>");
                   wcscat(SINVAttach,L"<Path>C:\\\\WINDOWS\\\\system32\\\\</Path>");
                   wcscat(SINVAttach,L"<ProductLanguage>1033</ProductLanguage>");
    wcscat(SINVAttach,L"<ProductName>Microsoft&#174;\\x0020Windows&#174;\\x0020Operating\\x0020System</ProductName>");
                   wcscat(SINVAttach,L"<ProductVersion>5.1.2600.2180</ProductVersion>");
                   wcscat(SINVAttach,L"<Size>69120</Size>");
                   wcscat(SINVAttach,L"</FileSystemFile>");
                   wcscat(SINVAttach,L"</Instance>");
                   wcscat(SINVAttach,L"</ReportBody>");
                   wcscat(SINVAttach,L"</Report>");
      _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) );

            //Use the SetClientID method (must have .c/.h files from KB917873)
         _CHECKHR( pRequest->QueryInterface(IID_ISmsMessage2, (void **) &pRequest2) );
           _CHECKHR( pRequest2->SetClientID(sClientID) );

           //Set Body (Header)
            _CHECKHR( pRequest2->SetBodyFromString(SINVBody) );

          //Get length of attachment
         size_t pcch;
            StringCchLengthW(SINVAttach,MAX_BUFFER_LENGTH,&pcch);
           ULONG uSize = pcch * 2;

         //Set Attachment
           _CHECKHR( pRequest2->SetAttachmentFromBuffer(
                        sReportID,
                        (const BYTE*)SINVAttach,
                        uSize) );
            
            //Set EndPoint
         _CHECKHR( pRequest2->SetTargetEndpoint(sEndPoint) );

         //Post Message
         _CHECKHR( pMessaging->Post(sMPName, pRequest2, &pszTrackingID) );

        _END

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

         if(pszTrackingID)
          {
               ::CoTaskMemFree(pszTrackingID);
         }
           return S_OK;

           pRequest2->Release();
        }
   }
   CoUninitialize();
   return nRetCode;
}