
/*++

    UMI_V6.IDL

    Universal Management Interfaces for Whistler WMI/DS Providers

    v1.01   raymcc      13-Jan-00       Second draft in preparation for meeting with ADSI team
    v1.02   raymcc      17-Jan-00       DS long meeting (Sanjes, alanbos, DS team)
    v1.03   raymcc      28-Jan-00       Updates after 'type system' meeting
    v1.04   raymcc      02-Feb-00       Compilable, slight reorg of COM inheritance
    v1.05   raymcc      03-Feb-00       Type system
    v1.06   raymcc      11-Feb-00       Type system cleanup after meeting with ADSI team
    v1.07   raymcc      15-Feb-00       Minor type system fixes
    v1.08   raymcc      22-Feb-00       Ajay's updates to type system
    v1.09   alanbos     22-Mar-00       Added IUmiCustomInterfaceFactory

--*/


[uuid(12575a7a-d9db-11d3-a11f-00105a1f515a)]

library UMI_V6
{
    importlib("stdole32.tlb");

    interface IUmiPropList;
    interface IUmiBaseObject;
    interface IUmiObject;
    interface IUmiConnection;
    interface IUmiContainer;
    interface IUmiCursor;
    interface IUmiObjectSink;
    interface IUmiURLKeyList;
    interface IUmiURL;
    interface IUmiQuery;
    interface IUmiCustomInterfaceFactory;

typedef enum tag_UMI_TYPE_ENUMERATION
{
    UMI_TYPE_NULL         =0,

    UMI_TYPE_I1         =1,
    UMI_TYPE_I2         =2,
    UMI_TYPE_I4         =3,
    UMI_TYPE_I8         =4,

    UMI_TYPE_UI1        =5,
    UMI_TYPE_UI2        =6,
    UMI_TYPE_UI4        =7,
    UMI_TYPE_UI8        =8,

    UMI_TYPE_R4           =9,
    UMI_TYPE_R8          =10,


    UMI_TYPE_FILETIME    =12,
    UMI_TYPE_SYSTEMTIME  =13,
    UMI_TYPE_BOOL        =14,
    UMI_TYPE_IDISPATCH   =15,
    UMI_TYPE_IUNKNOWN    =16,
    UMI_TYPE_VARIANT     =17,

    UMI_TYPE_LPWSTR         =20,
    UMI_TYPE_OCTETSTRING    =21,
    UMI_TYPE_UMIARRAY       =22,

    UMI_TYPE_DISCOVERY      =23,
    UMI_TYPE_UNDEFINED      =24,
    UMI_TYPE_DEFAULT        =25,

    UMI_TYPE_ARRAY_FLAG     =0x2000

}   UMI_TYPE_ENUMERATION;

// Allows for combining flags and such
typedef ULONG UMI_TYPE;

typedef enum
{
    UMI_GENUS_CLASS = 1,
    UMI_GENUS_INSTANCE = 2
} UMI_GENUS_TYPE;

typedef enum
{
    UMI_DONT_COMMIT_SECURITY_DESCRIPTOR = 0x10
} UMI_COMMIT_FLAGS;

typedef enum
{
    // Which properties to get
    UMI_FLAG_GETPROPS_ALL = 1,
    UMI_FLAG_GETPROPS_SCHEMA = 0x2, 
    UMI_MASK_GETPROPS_PROP = 0xFF,

    // Extended modifiers (e.g. just names, etc.)
    UMI_FLAG_GETPROPS_NAMES = 0x100,
    UMI_MASK_GETPROPS_EXT = 0x100
}   UMI_GETPROPS_FLAGS;

typedef enum
{
    // Return a property list of a property
    UMI_FLAG_OWNER_SECURITY_INFORMATION = 0x1,
    UMI_FLAG_GROUP_SECURITY_INFORMATION = 0x2,
    UMI_FLAG_DACL_SECURITY_INFORMATION  = 0x4,
    UMI_FLAG_SACL_SECURITY_INFORMATION  = 0x8,
    UMI_SECURITY_MASK                   = 0xF,
    UMI_FLAG_PROVIDER_CACHE             = 0x10, 
    // Retrieve property based on provider cache
    UMI_FLAG_PROPERTY_ORIGIN            = 0x20,
    // Get the origin class of the property
}   UMI_GET_FLAGS;

typedef enum
{
    UMI_FLAG_REFRESH_ALL = 0,                   // Refresh all properties from cache 
    UMI_FLAG_REFRESH_PARTIAL = 1                // Refresh untouched properties from cache
}   UMI_REFRESH_FLAGS;

typedef enum
{
    UMI_OPERATION_NONE = 0,                     // Set when a property is retrieved
    UMI_OPERATION_APPEND = 1,                   // DS supports this
    UMI_OPERATION_UPDATE = 2,                   // DS supports this
    UMI_OPERATION_EMPTY  = 3,                   // DS supports this
    UMI_OPERATION_INSERT_AT = 4,
    UMI_OPERATION_REMOVE_AT = 5,
    UMI_OPERATION_DELETE_AT = 6,
    UMI_OPERATION_DELETE_FIRST_MATCH = 7,       // DS supports this
    UMI_OPERATION_DELETE_ALL_MATCHES = 8,
    UMI_OPERATION_RESTORE_DEFAULT = 9
}   UMI_PROP_INSTRUCTION;

// These flags are used for operations such as Delete, which may apply to instances
// or classes and the path may be abiguous

typedef enum
{
    UMI_OPERATION_INSTANCE = 0X1000,            // operation is for instance
    UMI_OPERATION_CLASS = 0X2000
}   UMI_OPERATION_PATH;

typedef enum
{
          UMIPATH_CREATE_AS_NATIVE    = 0x8000,
          UMIPATH_CREATE_AS_EITHER    = 0x4000,
          UMIPATH_CREATE_ACCEPT_RELATIVE  = 0x4,
}   tag_UMI_PATH_CREATE_FLAG;

typedef enum tag_WMI_PATH_STATUS_FLAG
{
      UMIPATH_INFO_NATIVE_STRING          = 0x1,   //  path was set as native.
      UMIPATH_INFO_RELATIVE_PATH          = 0x2,   //  path has null server.
      UMIPATH_INFO_INSTANCE_PATH          = 0x4,   //  path has a key and/or value.
      UMIPATH_INFO_CLASS_PATH             = 0x8,
      UMIPATH_INFO_SINGLETON_PATH         = 0x10,

} tag_UMI_PATH_STATUS_FLAG;

///////////////////////////////////////////////////////////////////////
//
//  UMI ERROR CODES

/*
Standard codes from WINERROR.H:

    S_OK    (Zero) Success  
    E_ACCESS_DENIED Access denied (security violation)  
        
    E_NOINTERFACE   Interface not available (from QueryInterface only)  
    E_UNEXPECTED    Unhandled internal exception; should not be seen by client code 
    E_NOTIMPL   API is not implemented (this is not to be returned when a feature of the API is not implemented while other parts are)  
    E_OUTOFMEMORY   Insufficient system memory to comply with the request   
    E_FAIL  Generic failure of operation; call IUmiBaseObject::GetCallResult for more detail.   
    E_INVALIDARG    One or more arguments was not valid 

*/

// UMI-Specific Errors

typedef enum
{
    UMI_S_NO_ERROR = 0,

    UMI_E_CONNECTION_FAILURE = 0x80041001,

    UMI_E_TIMED_OUT                 = 0x80041002,      // Call timed out    
    UMI_E_TYPE_MISMATCH             = 0x80041003,      // Wrong value type supplied for a property  
    UMI_E_NOT_FOUND                 = 0x80041004,      // Object, property, etc. not found  
    UMI_E_INVALID_FLAGS             = 0x80041005,      // Flag mask was not a valid combination 
    UMI_E_UNSUPPORTED_FLAGS         = 0x80041006,      // Flags valid, but not supported in this case   
    UMI_E_SYNCHRONIZATION_REQUIRED  = 0x80041007,      // Internal cache requires a Commit or a Refresh before continuing   
    UMI_E_UNSUPPORTED_OPERATION     = 0x80041008,      // Operation is legal but unsupported in this provider   
    UMI_E_TRANSACTION_FAILURE       = 0x80041009,      // Transaction failed due to conflict with another transaction or forced rollback at the server  
    UMI_E_UNBOUND_OBJECT            = 0x8004100A       // The object is newly created and therefore unbound.

}   UMI_STATUS;

///////////////////////////////////////////////////////////////////////


typedef struct tag_UMI_OCTET_STRING
{
    ULONG uLength;
    byte  *lpValue;

}   UMI_OCTET_STRING, *PUMI_OCTET_STRING;


typedef struct tag_UMI_COM_OBJECT
{
    IID    *priid;
    LPVOID pInterface;

}   UMI_COM_OBJECT, *PUMI_COM_OBJECT;



    typedef union
    {
        CHAR         cValue[1];
        UCHAR        ucValue[1];
        WCHAR        wcValue[1];
        WORD         wValue[1];
        DWORD        dwValue[1];
        LONG         lValue[1];
        ULONG        uValue[1];
        BYTE         byteValue[1];
        BOOL         bValue[1];
        LPWSTR       pszStrValue[1];
        FILETIME     fileTimeValue[1];
        SYSTEMTIME   sysTimeValue[1];
        double       dblValue[1];

        unsigned __int64 uValue64[1];
        __int64          nValue64[1];
        UMI_OCTET_STRING octetStr[1];
        UMI_COM_OBJECT comObject[1];

    }   UMI_VALUE, *PUMI_VALUE;

    typedef struct
    {
        UMI_TYPE   uType;
        ULONG      uCount;              // Array fields of UMIVALUE only valid when used with this
        ULONG      uOperationType;
        LPWSTR     pszPropertyName;
        UMI_VALUE *pUMIValue;           // NULL when the value is actually NULL
    }   UMI_PROPERTY, *PUMI_PROPERTY;

    typedef struct
    {
        ULONG        uCount;
        UMI_PROPERTY *pPropArray;

    }   UMI_PROPERTY_VALUES, *PUMI_PROPERTY_VALUES;



///////////////////////////////////////////////////////////////////////


    //***********************************************************************
    // ok

    [object, local, uuid(12575a7c-d9db-11d3-a11f-00105a1f515a)]

    interface IUmiBaseObject : IUmiPropList
    {
        HRESULT GetLastStatus(
            [in]  ULONG uFlags,
            [out] ULONG *puSpecificStatus,
            [in]  REFIID riid,
            [out, iid_is(riid)] LPVOID *pStatusObj        // NULL=don't use
            );

        // Exports IErrorInfo, IUmiPropList
        // Changes after every call to an interface method

        HRESULT GetInterfacePropList(
            [in] ULONG uFlags,              // Overloaded
            [out] IUmiPropList **pPropList
            );
    };


    //***************************************************************************


    [object, local, uuid(12575a7b-d9db-11d3-a11f-00105a1f515a)]

    interface IUmiPropList : IUnknown
    {
        // This is IUmiObject without the connection implied by Refresh/Commit, etc.
        // It represents the property list portion of the object.

        HRESULT Put(
            [in] LPCWSTR pszName,
            [in] ULONG   uFlags,
            [in] UMI_PROPERTY_VALUES *pProp
            );

        HRESULT Get(
            [in]  LPCWSTR pszName,
            [in]  ULONG uFlags,
            [out] UMI_PROPERTY_VALUES **pProp
            );

        HRESULT GetAt(
            [in]  LPCWSTR pszName,
            [in]  ULONG uFlags,
            [in]  ULONG uBufferLength,       // Buffer size in bytes
            [out] LPVOID pExistingMem        // Single-valued UMI_LPWSTR and numeric types
            );

        HRESULT GetAs(
            [in]  LPCWSTR pszName,
            [in]  ULONG uFlags,
            [in]  ULONG uCoercionType,
            [out] UMI_PROPERTY_VALUES **pProp
            );

        HRESULT FreeMemory(
            ULONG  uReserved,
            LPVOID pMem
            );

        HRESULT Delete(
            [in] LPCWSTR pszName,
            [in] ULONG uFlags
            );


        // Functions for dealing with multiple properties at one time.
        // ===========================================================

        HRESULT GetProps(
            [in]  LPCWSTR *pszNames,
            [in]  ULONG uNameCount,
            [in]  ULONG uFlags,              // option: UMI_FLAG_GET_NAMES
            [out] UMI_PROPERTY_VALUES **pProps
            );
            // Also used for "GetNames" functionality.


        HRESULT PutProps(
            [in] LPCWSTR *pszNames,         // null-separated, double-null-terminated
            [in] ULONG uNameCount,
            [in] ULONG uFlags,              // PUT_WITH_COMMIT
            [in] UMI_PROPERTY_VALUES *pProps
            );


        HRESULT PutFrom(
            [in]  LPCWSTR pszName,
            [in]  ULONG uFlags,
            [in]  ULONG uBufferLength,
            [in] LPVOID pExistingMem
            );
    };


    //*******************************************************************
    // NOT CoCreatable; get this from IUmiPath.  This interface is used to
    // handle the multiple keys available in wmi.

    [local, object, uuid(cf779c98-4739-4fd4-a415-da937a599f2f)]

    interface IUmiURLKeyList : IUnknown
    {
        HRESULT GetCount(
            [out] ULONG * puKeyCount
            );

        HRESULT SetKey(
            [in, string] LPCWSTR pszName,
            [in, string] LPCWSTR pszValue
            );

        HRESULT GetKey(
            [in] ULONG uKeyIx,
            [in] ULONG uFlags,                     //  TBD as needed
            [in,out] ULONG * puKeyNameBufSize,
            [in] LPWSTR pszKeyName,                 // Set to key name
            [in,out] ULONG * puValueBufSize,
            [in] LPWSTR pszValue                    // Set to key value
            );

        HRESULT RemoveKey(
            [in, string] LPCWSTR pszName,
            [in] ULONG uFlags
            );

        HRESULT RemoveAllKeys(
            [in] ULONG uFlags
            );

        // UMIPATH_INFO_IS_GUID             <true if guid={}>

        HRESULT GetKeysInfo(
            [in] ULONG uRequestedInfo,
            [out] ULONGLONG *puResponse
            );

    };

    //***********************************************************************
    // This is the main interface.  It is a blend of the WMIPathParser and the
    // DS path cracker interfaces.

    [object, local, uuid(12575a7d-d9db-11d3-a11f-00105a1f515a)]

    interface IUmiURL : IUnknown
    {

        // Main functins for getting and setting the path

        HRESULT Set([in] long lFlags, [in] LPCWSTR pszText);    // see tag_UMI_PATH_CREATE_FLAG
        HRESULT Get([in] long lFlags, [in,out] ULONG * puBufSize, [in,string] LPWSTR pszDest);

        // Path tests.  To be determined.  As a minimum, could be used to check for
        // validity of created paths.

        HRESULT GetPathInfo(
            [in] ULONG uRequestedInfo,      // zero for now
            [out] ULONGLONG *puResponse     // see tag_UMI_PATH_STATUS_FLAG
            );

        // Locator (AKA Server) access

        HRESULT SetLocator(
            [in, string] LPCWSTR Name
            );

        HRESULT GetLocator(
            [in,out] ULONG * puNameBufLength,
            [in, string] LPWSTR pName
            );

        // Root namespace access.  This manipulates the "wmi" or "ds" part.
        // =============

        HRESULT SetRootNamespace(
            [in, string] LPCWSTR Name
            );

        HRESULT GetRootNamespace(
            [in,out] ULONG * puNameBufLength,
            [in, out, string] LPWSTR pName
            );

        // Component access.  The leftmost component is 0

        HRESULT GetComponentCount(
            [out] ULONG *puCount
            );

        HRESULT SetComponent(
            [in] ULONG uIndex,
            [in] LPWSTR pszClass
            );

        HRESULT SetComponentFromText(
            [in] ULONG uIndex,
            [in] LPWSTR pszText
            );

        HRESULT GetComponent(
            [in] ULONG uIndex,
            [in,out] ULONG * puClassNameBufSize,
            [in,out] LPWSTR pszClass,
            [out] IUmiURLKeyList **pKeyList
            );

        HRESULT GetComponentAsText(
            [in] ULONG uIndex,
            [in,out] ULONG * puTextBufSize,
            [in,out] LPWSTR pszText
            );

        HRESULT RemoveComponent(
            [in] ULONG uIndex
            );

        HRESULT RemoveAllComponents(
            );

        // The rightmost component is treated specially.  Both the wmi path parser and ds
        // path crackers do this.

        HRESULT SetLeafName(
            [in, string] LPCWSTR Name
            );

        HRESULT GetLeafName(
            [in,out] ULONG * puBuffLength,
            [in, out, string] LPWSTR pszName
            );

        HRESULT GetKeyList(
            [out] IUmiURLKeyList ** pOut
            );

        HRESULT CreateLeafPart(
            [in] long lFlags,
            [in, string] LPCWSTR Name
            );

        HRESULT DeleteLeafPart(
            [in] long lFlags
            );
    };


    //***********************************************************************
    // ok

    [object, local, uuid(12575a7e-d9db-11d3-a11f-00105a1f515a)]

    interface IUmiQuery : IUmiBaseObject
    {
        HRESULT Set(
            [in] LPCWSTR pszLanguage,
            [in] ULONG uFlags,
            [in] LPCWSTR pszText
            );


        HRESULT GetQuery(
            [in, out] ULONG * puLangBufSize,
            [in, out] LPWSTR pszLangBuf,
            [in, out] ULONG * puQueryTextBufSize,
            [in, out] LPWSTR pszQueryTextBuf
            );

            /* Houses the query properties.  Typically, query for
               IUmiObject or IUmiObjectMulti, so that all properties
               can be retrieved/set/deleted in one call.
            */

        // Query info also exposed as properties:
        //  "QUERYTEXT"     = "select * from Foo"
        //  "QUERYLANGUAGE" = "SQL"
    };


    //***********************************************************************
    // ok


    [object, local, uuid(5ed7ee26-64a4-11d3-a0da-00105a1f515a)]

    interface IUmiCursor : IUmiBaseObject
    {
        // Timeout settings, etc.  available from GetInterfacePropList

        HRESULT SetIID([in] REFIID riid);
            // IUmiObject by default if you never call this
            // Takes effect immediately after

        HRESULT Reset();
            // Must move to true beginning of enumeration or return E_NOTIMPL

        HRESULT Next(
            [in]  ULONG uNumRequested,
            [out] ULONG *puNumReturned,
            [out, size_is(uNumRequested), length_is(*puNumReturned)] LPVOID *pObjects
            );

        HRESULT Count(
            [out] ULONG *puNumObjects
            );
            // May return E_NOTIMPL

        HRESULT Previous(
            [in] ULONG uFlags,
            [out] LPVOID *pObj
            );
            // May return E_NOTIMPL
    };


    //***********************************************************************
    // ok

    [object, local, uuid(5ed7ee20-64a4-11d3-a0da-00105a1f515a)]

    interface IUmiConnection : IUmiBaseObject
    {
        HRESULT Open(
            [in]  IUmiURL *pURL,
            [in]  ULONG uFlags,
            [in]  REFIID TargetIID,
            [out, iid_is(TargetIID)] void **ppvRes
            );

        // Timeouts, etc., are configured using a call to GetInterfaceProps
    };


    //***********************************************************************
    // ok

    [object, local, uuid(5ed7ee21-64a4-11d3-a0da-00105a1f515a)]

    interface IUmiContainer : IUmiObject
    {

        HRESULT Open(
            [in]  IUmiURL *pURL,
            [in]  ULONG uFlags,                 // UMI_OPERATION_PATH
            [in]  REFIID TargetIID,
            [out, iid_is(TargetIID)] void **ppvRes
            );

/*
        HRESULT Get(
            [in] IUmiURL *pURL,
            [in] ULONG uFlags,
            [in] REFIID TargetIID,
            [out, iid_is(TargetIID)] void **ppvResult
            );
*/

        HRESULT PutObject(
            [in] ULONG uFlags,
            [in] REFIID TargetIID,
            [in, out, iid_is(TargetIID)] void *pObj
            );
            // May return E_NOTIMPL, as there is overlap with IUmiObject::Commit


        HRESULT DeleteObject(
            [in] IUmiURL *pURL,
            [in, optional]  ULONG uFlags         // UMI_OPERATION_PATH
            );

        HRESULT Create(
            [in]  IUmiURL *pURL,
            [in]  ULONG uFlags,                 // UMI_OPERATION_PATH
            [out] IUmiObject **pNewObj
            );

        HRESULT Move(
            [in] ULONG uFlags,
            [in] IUmiURL *pOldURL,
            [in] IUmiURL *pNewURL
            );

        HRESULT CreateEnum(
            [in]  IUmiURL *pszEnumContext,      // class name, etc. etc.
            [in]  ULONG uFlags,                 // UMI_OPERATION_PATH
            [in]  REFIID TargetIID,
            [out, iid_is(TargetIID)] void **ppvEnum
            );

        HRESULT ExecQuery(
            [in]  IUmiQuery *pQuery,
            [in]  ULONG uFlags,
            [in]  REFIID TargetIID,
            [out, iid_is(TargetIID)] void **ppResult
            );
    };


    //***********************************************************************
    // ok
    // Since this is a callback, there is little reason to have interface
    // properties. Not only that, the minimum implementation is too heavy;
    // this interface is supposed to be implemented by the client side,
    // so deriving from IUmiBaseObject is too much.
    //

    [object, local, uuid(5ed7ee24-64a4-11d3-a0da-00105a1f515a)]

    interface IUmiObjectSink : IUnknown
    {
        HRESULT Put(
            [in] LONG lNumObjects,
            [in, size_is(lNumObjects)] IUmiObject **ppObjects
            );

        HRESULT SetResult(
            [in] HRESULT hResStatus,
            [in] ULONG uFlags,
            [in] IUnknown *pObject         // QI for IErrorInfo, IUmiObject, etc.
            );
    };


    //***********************************************************************
    // ok

    [object, local, uuid(5ed7ee23-64a4-11d3-a0da-00105a1f515a)]

    interface IUmiObject : IUmiBaseObject
    {
        // Get/Put is on IUmiBaseObject

        HRESULT Clone(
            [in]  ULONG uFlags,
            [in]  REFIID riid,
            [out, iid_is(riid)] LPVOID *pCopy
            );

            /*
            Clones the current object exactly, including any connections and alternate interfaces, if possible.
            <uFlags> = should this allow cloning of entire connections or just the IUmiObject/PropList part, etc?
            */

        HRESULT CopyTo(
            [in]  ULONG uFlags,
            [in]  IUmiURL *pURL,
            [in]  REFIID riid,
            [out, iid_is(riid)] LPVOID *pCopy
          );

        HRESULT Refresh(
            [in] ULONG uFlags,
            [in] ULONG uNameCount,
            [in] LPWSTR *pszNames
            );

        HRESULT Commit(
            [in] ULONG uFlags
            );

            /*
            uFlags == CREATE_ONLY  UPDATE_ONLY  CREATE_OR_UDPATE = 0 (default)
            */


        // Security Descriptor is a standard property, not an API

    };

    [restricted, uuid(d4b21cc2-f2a5-453e-8459-b27f362cb0e0)]
    coclass UmiDefURL
    {
        interface IUmiURL;
    };


    //***********************************************************************
    //
    // This should always be QI'able from IUmiObject. It is not derived from
    // IUmiBaseObject since we assume that that functionality is taken care of
    // by IUmiObject.

    [object, local, uuid(14CD599E-2BE7-4c6f-B95B-B150DCD93585)]

    interface IUmiCustomInterfaceFactory : IUnknown
    {
        // Returns matching CLSID for requested IID
        HRESULT GetCLSIDForIID (
            [in] REFIID riid,               // IID to match on  
            [in] long lFlags,               // Reserved. Must be 0
            [in, out] CLSID *pCLSID         // returned CLSID
        );

        // Creates (possibly aggregated) object of given CLSID and returns interface
        HRESULT GetObjectByCLSID (
            [in]  CLSID clsid,                      // The CLSID to create
            [in]  IUnknown *pUnkOuter,              // Outer unknown for aggregation
            [in]  DWORD dwClsContext,               // Context for running executable code
            [in]  REFIID riid,                      // Requested interface
            [in]  long lFlags,                      // Reserved. Must be 0
            [out, iid_is(riid)] void **ppInterface  // Returned interface
            );

        // Provides DISPIDs for Names and the CLSID for the object that supports them
        HRESULT GetCLSIDForNames(
            [in, size_is(cNames)] LPOLESTR * rgszNames,     
            [in] UINT cNames,                               
            [in] LCID lcid,
            [out, size_is(cNames)] DISPID * rgDispId,
            [in]  long lFlags,                              // Reserved. Must be 0
            [in, out] CLSID *pCLSID                         // The supporting CLSID (if found)
            );
    };
};


