Let's talk about Server Extension Objects (SEO)
Published Jul 01 2005 12:09 PM 1,319 Views

I’ve worked for Microsoft for about 8 years, all in the Exchange group, and I really enjoy it.  The people who work here are bright, self-motivated, and we have the resources we need to get our jobs done.  It feels great to ship world-class products that our customers love.  However, not everything is perfect, it never is.  As my father-in-law once said, “It’s not all grapes and gravy.”  For example, the engineering group must work well together with the user education group to produce documentation that lets customers easily get the most out of the software we’ve produced.   The single most frustrating episode I’ve endured has to do with the documentation for SEO, or the relative lack thereof.  It’s not like I’m free of blame here, I worked on SMTP when these Server Extension Objects (SEO) were first implemented many years ago.  So without further adieu, let’s talk about what I think should have been documented about SEO.  Please read on, if you’d like to learn a little bit more about a soon-to-be obsolete technology (it will remain in some SKUs of Windows SMTP, but will be replaced in E12), and help me get something off my mind at the same time.


Let’s first describe SEO a bit.  SEO is a COM-based technology that allows customization of the Windows SMTP service.  In the SEO model, information flows from the source (the SMTP server) to the sink (the SEO COM object), whenever an interesting event in processing an SMTP connection is reached.  After the SMTP server is finished calling all the sinks, it then proceeds with handling the SMTP session, guided by the actions of the sinks.  The last piece of the puzzle is the event bindings database, where the ordered collection of sinks to call for each processing event is persisted.  One piece of code that customizes the Windows SMTP service is Exchange 2000/2003.  Without the customization and extension made possible by SEO, Exchange would not be the compelling mail server that it is.


So let’s pick apart the parts of the IIS metabase that contains the SEO information, and we’ll discover an object model along the way.  To get us started, let’s use the adsutil.vbs script that comes with an IIS install, to inspect the “eventmanager” part of the metabase.  If you run “cscript.exe %systemdrive%\inetpub\adminscripts\adsutil.vbs /enum_all eventmanager” you’ll see a big bunch of unintelligible output.  Let’s dissect just a fraction of it:




What does this mean?  The first GUID can be seen in the public SDK file SmtpGuid.h, where it is given the name g_szGuidSmtpSourceType.  The second GUID, located in the same file, corresponds with g_szcatidSmtpOnInboundCommand.  To understand the rest of the string, we need to take a quick peek at the SEO object model.


The root object here is IEventManager, which has a programmatic ID of “Event.Manager”, and is reflected in the “eventmanager” string.  This object is the one you create and use to get at all the rest of the SEO entities.  The IEventManager object contains an IEventSourceTypes object (please notice the “s” at the end here, we’ll see other similarly-named collection classes later), and the IEventSourceTypes object just contains a collection of IEventSourceType objects.  Each IEventSourceType object contains an IEventTypes object, which, of course, just contains a set of IEventType objects.  So, if we re-parse the string above, we can read it as telling us that the IEventManager contains an IEventSourceType with the ID {FB65C4DC-E468-11D1-AA67-00C04FA345F6}, and that this source knows how to generate {F6628C8D-0D5E-11d2-AA68-00C04FA35B82}, or g_szcatidSmtpOnInboundCommand, events.


The rest of the info in the eventmanager part of the IIS metabase serves the same purpose, to define the two sources of SEO events, the SMTP and NNTP server, and to list the types of events that each source may generate.


The other SEO information, which describes which consumers are to be called for which SEO event types, and in what order, is located in other parts of the metabase.  For example, the first SMTP virtual server has its SEO information listed under smtpsvc/1/eventmanager.  So if you type “cscript.exe %systemdrive%\inetpub\adminscripts\adsutil.vbs enum_all smtpsvc/1/eventmanager”, you’ll see info like














What could this mean?  The first portion of the string -- /smtpsvc/1/eventmanager/ -- just lets us know we are looking at the IEventSource for the first SMTP virtual server instance.  Note that there is a difference between an IEventSourceType and an IEventSource.  The IEventSourceType is an abstract, like “SMTP server”, while the IEventSource is a literal instance, like “the first SMTP virtual server instance on this machine”.  The next part of the string -- EventTypes/{F6628C8F-0D5E-11d2-AA68-00C04FA35B82} -- tells us we are looking at the g_szcatidSmtpOnInboundCommand event type.  To understand the rest of the string, we need to hearken back to the SEO object model, which defines the IEventSource as containing an IEventBindingManager object.  The IEventBindingManager object is used to read, write, create, and destroy IEventBinding objects.  There is one IEventBinding object contained in the metabase for each point of customization between the SMTP server and external code.  The event binding is how this customization is persisted when IIS is recycled or the system restarted.  Finally, the IEventBinding object contains an IEventPropertyBag object, which allows the event binding to contain additional information about itself.


Now that we know a little more, we can look at the second fragment of output and see that it’s referring to information regarding an SEO binding.  The binding is attached to the first virtual SMTP server instance, and it’s for the SmtpOnInboundCommand event type.  The binding has a few properties, too.  But why can’t we see more?  It turns out that the adsutil.vbs script makes use of the ADSI schema for the metabase to understand and display the data contained in the metabase.  The SEO information is not contained in the ADSI schema, and so doesn’t display much interesting information at all.


If we run the “displaybindings” script (see near the end of this posting for the full vbs script), we’ll see some more descriptive detail displayed:


    \Source Types\Sources\Bindings\{F6628C8D-0D5E-11d2-AA68-00C04FA35B82}

      Display Name = SMTP Protocol OnInboundCommand

      ID = {2EFF593B-5451-4D20-891C-1D32BFE95A1C}

        priority = 9000

        rule = X-EXPS

        SinkClass = Exchange.PS-EXPS

        DisplayName = Exchange SMTP Protocol Security EXPS Sink


The SEO information looks a little nicer.  We have a bit more context given to the GUIDs, and we can see all of the properties and their values.  All of the other information under /smtpsvc/1/eventmanager/ is there for the same purpose, to describe event bindings.


Now we’ve looked at the SEO object model a bit, as well as pulled apart the SEO information in the metabase.  And we’ve mentioned that SEO is not part of our future product shipments.  I would describe ways you can use SEO to improve your system, but there really aren’t any.  SEO information should just be left alone, there is nothing to be gained from tweaking it.


So just as we’ve started, we’re already done.  If you have more questions about SEO, or the customization that can be gained from working with it, take a look at MSDN, and let us know if you have any more questions.  It was interesting, from my side, to get this technology out into the world, and it would be interesting to hear from you how you’re using it.


Here is the content of the displaybindings vbs script:


Option Explicit


'       \nt\private\inet\iis\staxinc\export\smtpdisp.idl


Const catidPtSourceType =     "{FB65C4DC-E468-11D1-AA67-00C04FA345F6}"

Const catidPtSmtpSvc =        "{1B3C0666-E470-11D1-AA67-80C04FA345F6}"


REM ========================================================================================================

REM Function:

REM   e                    -- keystroke saver for WScript.Echo


REM Arguments:

REM   strMessage           -- message to echo to screen


REM ========================================================================================================

Sub e (strMessage)

        WScript.Echo strMessage

End Sub


REM ========================================================================================================

REM Function:

REM   WriteCollection      -- echoes a property bag


REM Arguments:

REM   objCollection        -- object to write (must implement _NewEnum)


REM ========================================================================================================

Sub WriteCollection(objCollection)

  Dim strProperty


  For Each strProperty In objCollection

    If IsObject(objCollection(strProperty)) Then

      WriteCollection objCollection(strProperty)


      e strProperty & " = " & objCollection(strProperty)

    End If


End Sub


Function GetEventTypeDesc(strEventType)

      On Error Resume Next

      Dim strRetVal

      Dim objComCat

      Set objComCat = CreateObject("Event.ComCat")


      strRetVal = objComCat.GetCategoryDescription(strEventType,0)

      If(0 = Len(strRetVal)) Then

            strRetVal = "Unknown (" & strEventType & ")"

      End If


      Set objComCat = Nothing


      GetEventTypeDesc = strRetVal

End Function


Dim objEventManager

Dim objEventUtil

Dim GUID_SourceGuid

Dim strEventType

Dim objBindingManager

Dim objBindings

Dim objBinding

Dim strEventTypeDesc


' create server event objects


Set objEventManager = CreateObject("Event.Manager")

Set objEventUtil = CreateObject("Event.Util")


' make source guid for instance 1


GUID_SourceGuid = objEventUtil.GetIndexedGUID(catidPtSmtpSvc,CLng(1))


' get binding manager


Set objBindingManager = objEventManager.SourceTypes(catidPtSourceType).Sources(GUID_SourceGuid).GetBindingManager


' iterate through the event types


For Each strEventType In objBindingManager

      strEventTypeDesc = GetEventTypeDesc(strEventType)

  e "Event Type : " & strEventTypeDesc 'strEventType

  e "===================================================="

  Set objBindings = objBindingManager.Bindings(strEventType)

  For Each objBinding In objBindings

    WriteCollection objBinding.EventBindingProperties

    e ""


  e ""



' cleanup


Set objEventManager = Nothing

Set objEventUtil = Nothing


- Ed Prescott

Version history
Last update:
‎Jul 01 2019 03:06 PM
Updated by: