locked
MSDN OLE DB Sample Provider entry point RRS feed

  • Question

  • Hello everyone,


    I have built MSDN OLE DB Sample Provider and successfully built/debug it using Microsoft Excel as client. I have found that in DllGetClassObject (classfac.cpp), the class SampProv is initialized as the 1st coclass, then DataSource object will be created in QueryInterface.

    http://msdn2.microsoft.com/en-us/library/ms715011.aspx

    The entry point of a COM server (like this Sample OLE DB Provider) is creating a coclass through DllGetClassObject. My question is, how did Microsoft Excel find the entry point coclass of the OLE DB Provider is SampProv coclass?

    I have this question because Excel is a client with no knowledge about any specific application defined CLSID, like SampProv, how could it be aware of this ID (i.e. Excel knows nothing about 3rd party application's specific name of entry point coclass)? In Windows registry, I can not find any related information indicating that SampProv should be the entry point coclass either.


    thanks in advance,
    George

    Saturday, July 21, 2007 1:33 PM

Answers

  • The Platform SDK forums and newsgroups would probably be a better place to ask this question. That said, it's the standard COM story. CoGetClassObject looks up the information (including the implementation DLL for Inproc servers) in HKCR\CLSID\<CLSID>. CoCreateInstance is merely a wrapper that directly creates an object instance.

     

    Now Excel certainly wouldn't connect to your OLEDB Provider unless you told it to. There are registry entries that define a provider/enumerator and the root enumerator walks the registry to find these. The OLEDB Data Links UI uses that information to present a list of available providers. Once you select a provider, the system uses its corresponding CLSID to create an instance of the provider.

     

    -hg

     

    Saturday, July 21, 2007 3:46 PM
  • Quite honestly, these are rather fundamental COM concepts and you might have a hard time implementing a full-blown OLE/DB provider with that.

     

    Anyway, here's how it looks like for the SQL Server Driver:

     

    Code Snippet

    [HKEY_CLASSES_ROOT\SQLOLEDB.1]
    @="Microsoft OLE DB Provider for SQL Server"

    [HKEY_CLASSES_ROOT\SQLOLEDB.1\Clsid]
    @="{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}"

     

    SQLOLEDB.1 is the progid. This is how you create COM objects directly in scripts (new ActiveXObject("SQLOLEDB.1") in JScript or CreateObject("SQLOLEDB.1") in VBS).

     

    {0C7FF16C-38E3-11d0-97AB-00C04FC2AD98} is the textual representation of the CLSID. As you can see it has 32 significant hex digits = 128 bits.

     

    The mapping is done by CLSIDFromProgId.

     

    Now the CLSID key is here:

     

    Code Snippet

    HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}]
    @="SQLOLEDB"
    "OLEDB_SERVICES"=dword:ffffffff

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\ExtendedErrors]
    @="Extended Error Service"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\ExtendedErrors\{C0932C62-38E5-11d0-97AB-00C04FC2AD98}]
    @="SQLOLEDB Error Lookup"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\Implemented Categories]

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\Implemented Categories\{D267E19A-0B97-11D2-BB1C-00C04FC9B532}]

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\InprocServer32]
    @="C:\\Program Files\\Common Files\\System\\Ole DB\\sqloledb.dll"
    "ThreadingModel"="Both"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\OLE DB Provider]
    @="Microsoft OLE DB Provider for SQL Server"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\ProgID]
    @="SQLOLEDB.1"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\VersionIndependentProgID]
    @="SQLOLEDB"

     

    The "OLE DB Provider" subkey marks it as an OLE DB Provider (remember the Root Enumerator walks the entire HKCR\CLSID subtree). CoGetClassObject looks up the HKCR\CLSID\<clsid provided as parameter to CoGetClassObject> key. For in-proc servers, it will load the named DLL and call the export DllGetClassObject with the supplied CLSID. CoCreateInstance is just a wrapper around CoGetClassObject followed by a IClassFactory->CreateInstance.

     

    -hg

     

     

     

    Tuesday, July 24, 2007 1:36 PM

All replies

  • The Platform SDK forums and newsgroups would probably be a better place to ask this question. That said, it's the standard COM story. CoGetClassObject looks up the information (including the implementation DLL for Inproc servers) in HKCR\CLSID\<CLSID>. CoCreateInstance is merely a wrapper that directly creates an object instance.

     

    Now Excel certainly wouldn't connect to your OLEDB Provider unless you told it to. There are registry entries that define a provider/enumerator and the root enumerator walks the registry to find these. The OLEDB Data Links UI uses that information to present a list of available providers. Once you select a provider, the system uses its corresponding CLSID to create an instance of the provider.

     

    -hg

     

    Saturday, July 21, 2007 3:46 PM
  • Thanks Holger,

     

     

     Holger Grund wrote:

    The Platform SDK forums and newsgroups would probably be a better place to ask this question. That said, it's the standard COM story. CoGetClassObject looks up the information (including the implementation DLL for Inproc servers) in HKCR\CLSID\<CLSID>. CoCreateInstance is merely a wrapper that directly creates an object instance.

     

    Now Excel certainly wouldn't connect to your OLEDB Provider unless you told it to. There are registry entries that define a provider/enumerator and the root enumerator walks the registry to find these. The OLEDB Data Links UI uses that information to present a list of available providers. Once you select a provider, the system uses its corresponding CLSID to create an instance of the provider.

     

    -hg

     

     

    Could you recommend some more related Platform SDK forums and newsgroups? :-)

     

     > Once you select a provider, the system uses its corresponding CLSID to create an instance of the provider.

     

    I can understand this point. But if we think in more details, when a provider is selected, how could the system finds the corresponding CLSID? Where do we bind the corresponding CLSID and the provider?

     

     

    regards,

    George

    Sunday, July 22, 2007 5:42 AM
  • You may want to look here

    As I understand the root enumerator (this is a COM object provided by OLE/DB Core with a predefined CLSID) walks the entire HKEY_CLASS_ROOT\CLSID subkey. Whenever it sees a <CLSID> key with some subkey or value that identifies an OLE/DB provider or enumerator it just adds it to its internal table.

     

    So if it sees HKCR\CLSID\{4711-..0815}\OLE DB Provider\@default = "My Provider" it adds a mapping

    {4711-..0815} <=> "My Provider"

     

    You can read up more here http://msdn2.microsoft.com/en-us/library/ms711269.aspx and under registry entries in linked from there.

     

    -hg

     

    Sunday, July 22, 2007 10:55 AM
  • Thanks Holger,

     

     

     Holger Grund wrote:

    You may want to look here

    As I understand the root enumerator (this is a COM object provided by OLE/DB Core with a predefined CLSID) walks the entire HKEY_CLASS_ROOT\CLSID subkey. Whenever it sees a <CLSID> key with some subkey or value that identifies an OLE/DB provider or enumerator it just adds it to its internal table.

     

    So if it sees HKCR\CLSID\{4711-..0815}\OLE DB Provider\@default = "My Provider" it adds a mapping

    {4711-..0815} <=> "My Provider"

     

    You can read up more here http://msdn2.microsoft.com/en-us/library/ms711269.aspx and under registry entries in linked from there.

     

    -hg

     

     

    Root Enumerator Object I think should be some core component of underlying OLE DB engine. I am implementing a simple OLE DB provider using C# and I think from OLE DB provider point of view, we should not implement such object in OLE DB provider, right?

     

    My question is, how could Excel (or Root Enumerator Object or some other component) finds the entry point of OLE DB provider coclass? For Microsoft Sample Provider, the entry coclass (CLSID) should be SampProv, and for SQL Server, it should be CLSID_SQLOLEDB. I am wondering how Excel finds such different names specific to different provider.

     

    If I am implementing an OLE DB provider, how could I expose the extry coclass name to Excel?

     

     

    regards,

    George

    Sunday, July 22, 2007 1:04 PM
  • Yes, you don't implement the root enumerator - it is provided the OLE/DB core components. You simply register your own provider or your own enumerator with the root enumerator. This is done by adding the appropriate subkey under your component's CLSID key.

     

    Now when you select "Data" -> "Import External Data" -> "Import Data" -> "New Data Source" -> "Other/Advanced" you see a OLE/DB standard dialog (IIRC it's called Data Links UI).

     

    You see there exactly the providers that the root enumerator lists. The display name is the default value of the registry subkey "OLE DB Provider" (e.g. SampProv). The corresponding CLSID would be the name of the parent registry key. Note that the CLSID is a GUID - a 128 bit numeric identifiers. CLSID_SQLOLEDB is just a variable that refers to the corresponding numeric identifier. It is not meaningful outside the source code.

     

    You might confuse that with a ProgId (which is a human-readable equivalent for a CLSID). This again is looked up in the registry (this time directly under HKCR) to find the corresponding CLSID.

     

    -hg

    Sunday, July 22, 2007 2:31 PM
  • Thanks Holger,

     

     

     Holger Grund wrote:

    Yes, you don't implement the root enumerator - it is provided the OLE/DB core components. You simply register your own provider or your own enumerator with the root enumerator. This is done by adding the appropriate subkey under your component's CLSID key.

     

    Now when you select "Data" -> "Import External Data" -> "Import Data" -> "New Data Source" -> "Other/Advanced" you see a OLE/DB standard dialog (IIRC it's called Data Links UI).

     

    You see there exactly the providers that the root enumerator lists. The display name is the default value of the registry subkey "OLE DB Provider" (e.g. SampProv). The corresponding CLSID would be the name of the parent registry key. Note that the CLSID is a GUID - a 128 bit numeric identifiers. CLSID_SQLOLEDB is just a variable that refers to the corresponding numeric identifier. It is not meaningful outside the source code.

     

    You might confuse that with a ProgId (which is a human-readable equivalent for a CLSID). This again is looked up in the registry (this time directly under HKCR) to find the corresponding CLSID.

     

    -hg

     

    I generally agree and understand your points. But confused about some details,

     

    1. the name of the parent registry key;

    2. ProgId

     

    I am not quite clear about your context about parent registry key and ProgId. It is appreciated if you could post a simple sample for detailed points. Thanks.

     

     

    regards,

    George

    Monday, July 23, 2007 12:21 PM
  • Quite honestly, these are rather fundamental COM concepts and you might have a hard time implementing a full-blown OLE/DB provider with that.

     

    Anyway, here's how it looks like for the SQL Server Driver:

     

    Code Snippet

    [HKEY_CLASSES_ROOT\SQLOLEDB.1]
    @="Microsoft OLE DB Provider for SQL Server"

    [HKEY_CLASSES_ROOT\SQLOLEDB.1\Clsid]
    @="{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}"

     

    SQLOLEDB.1 is the progid. This is how you create COM objects directly in scripts (new ActiveXObject("SQLOLEDB.1") in JScript or CreateObject("SQLOLEDB.1") in VBS).

     

    {0C7FF16C-38E3-11d0-97AB-00C04FC2AD98} is the textual representation of the CLSID. As you can see it has 32 significant hex digits = 128 bits.

     

    The mapping is done by CLSIDFromProgId.

     

    Now the CLSID key is here:

     

    Code Snippet

    HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}]
    @="SQLOLEDB"
    "OLEDB_SERVICES"=dword:ffffffff

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\ExtendedErrors]
    @="Extended Error Service"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\ExtendedErrors\{C0932C62-38E5-11d0-97AB-00C04FC2AD98}]
    @="SQLOLEDB Error Lookup"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\Implemented Categories]

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\Implemented Categories\{D267E19A-0B97-11D2-BB1C-00C04FC9B532}]

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\InprocServer32]
    @="C:\\Program Files\\Common Files\\System\\Ole DB\\sqloledb.dll"
    "ThreadingModel"="Both"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\OLE DB Provider]
    @="Microsoft OLE DB Provider for SQL Server"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\ProgID]
    @="SQLOLEDB.1"

    [HKEY_CLASSES_ROOT\CLSID\{0C7FF16C-38E3-11d0-97AB-00C04FC2AD98}\VersionIndependentProgID]
    @="SQLOLEDB"

     

    The "OLE DB Provider" subkey marks it as an OLE DB Provider (remember the Root Enumerator walks the entire HKCR\CLSID subtree). CoGetClassObject looks up the HKCR\CLSID\<clsid provided as parameter to CoGetClassObject> key. For in-proc servers, it will load the named DLL and call the export DllGetClassObject with the supplied CLSID. CoCreateInstance is just a wrapper around CoGetClassObject followed by a IClassFactory->CreateInstance.

     

    -hg

     

     

     

    Tuesday, July 24, 2007 1:36 PM