none
OLE in a Service doensn't work RRS feed

  • Question

  • Hi all,

    I'm not a specialist in OLE. I got a project with a working OLE functionality and a test program. My job is to put the existing OLE functionality to a service and the OLE has to work without any changes on the test program.

    I created a service via:

    VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv);
    VOID WINAPI ServiceCtrlHandler (DWORD);
    DWORD WINAPI ServiceWorkerThread (LPVOID lpParam);

    and I called the OLE functionality in the ServiceWorkerThread.

    if (!AfxOleInit())
    {
    	// AfxMessageBox(IDP_OLE_INIT_FAILED);
    	return FALSE;
    }
    
    // This provides a NULL DACL which will allow access to everyone.
    CSecurityDescriptor sd;
    sd.InitializeFromThreadToken();
    hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    //hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_PKT, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    _ASSERTE(SUCCEEDED(hr));
    
    AFX_MANAGE_STATE(AfxGetStaticModuleState());
    if (!AfxOleRegisterTypeLib(AfxGetInstanceHandle(), LIBID_S7WMEDAX))
    	return SELFREG_E_TYPELIB;
    if (!COleObjectFactory::UpdateRegistryAll())
    	return SELFREG_E_CLASS;

    All OLE calls work without error. Startig the test program I got during

     AfxGetClassIDFromString(LPCTSTR lpsz, LPCLSID lpClsID)

    the following error: Ungültige Klassenzeichenfolge --> Invalid class string

    Has any body an idea?


    Monday, June 3, 2019 11:53 AM

All replies

  • The MFC AfxGetClassIDFromString function is a wrapper that can call either CLSIDFromString or CLSIDFromProgID.

    CLSIDFromString returns the error code CO_E_CLASSSTRING if "The class string was improperly formatted."

    CLSIDFromProgID returns the same error code if  "The registered CLSID for the ProgID is invalid."

    Monday, June 3, 2019 12:35 PM
  • Hello,

    how do you call AfxGetClassIDFromString? According to your call, you must check the corresponding function.

    HRESULT AFXAPI AfxGetClassIDFromString(LPCTSTR lpsz, LPCLSID lpClsID)
    {
      USES_CONVERSION;
    
      HRESULT hr;
      if (lpsz[0] == '{')
        hr = CLSIDFromString((LPOLESTR)T2COLE(lpsz), lpClsID);
      else
        hr = CLSIDFromProgID(T2COLE(lpsz), lpClsID);
      return hr;
    } 

    https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-clsidfromstring

    https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-clsidfromprogid

    Regards, Guido

    Monday, June 3, 2019 12:53 PM
  • Most OLE controls are in-process COM servers (that is, in a DLL).  Does your OLE code already work as a normal out-of-process server?  Or does it assume it is in-process?

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Monday, June 3, 2019 6:22 PM
  • Hello,

    Thank you for posting here.

    >>the following error: Ungültige Klassenzeichenfolge --> Invalid class string

    This error corresponds to this two functions:CLSIDFromString() and CLSIDFromProgID(). Their Microsoft Document Links are as follows for your reference:

    https://docs.microsoft.com/en-us/windows/desktop/api/combaseapi/nf-combaseapi-clsidfromprogid

    https://docs.microsoft.com/en-us/previous-versions/aa911288(v%3dmsdn.10)

    As far as I'm concerned, this is probably related to the parameter settings of your function AfxGetClassIDFromString. 

    Best Regards,

    Suarez Zhou

    Tuesday, June 4, 2019 9:42 AM
  • Most OLE controls are in-process COM servers (that is, in a DLL).  Does your OLE code already work as a normal out-of-process server?  Or does it assume it is in-process?

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    I've a copy of my OLE functionality without the service handling. This code works fine with my OLE test application. If I put my handling for service around this working OLE functionality I got the error message. I start the OLE functionality in the ServiceWorkerThread of my service.

    I think the problem is the service around my OLE functionality, but I've no idea, what I must do.

    Tuesday, June 4, 2019 10:15 AM
  • Services run in an isolated, non-interactive session -- session 0.  This was implemented beginning with Windows Vista to enhance security by protecting highly privileged services from attack. So depending on what your "OLE functionality" is, it is possible that this security barrier is coming into play.
    Tuesday, June 4, 2019 10:20 AM
  • Services run in an isolated, non-interactive session -- session 0.  This was implemented beginning with Windows Vista to enhance security by protecting highly privileged services from attack. So depending on what your "OLE functionality" is, it is possible that this security barrier is coming into play.
    I think You are right. But can You give me a tip, how I can solve this problem? I've no idea!
    Tuesday, June 4, 2019 10:31 AM
  • Start by telling us exactly what you mean by "OLE Functionality".
    Tuesday, June 4, 2019 10:33 AM
  • Start by telling us exactly what you mean by "OLE Functionality".
    if (!AfxOleInit())
    {
    	// AfxMessageBox(IDP_OLE_INIT_FAILED);
    	return FALSE;
    }
    
    // This provides a NULL DACL which will allow access to everyone.
    CSecurityDescriptor sd;
    sd.InitializeFromThreadToken();
    hr = CoInitializeSecurity(sd, -1, NULL, NULL, RPC_C_AUTHN_LEVEL_CALL, RPC_C_IMP_LEVEL_IMPERSONATE, NULL, EOAC_NONE, NULL);
    _ASSERTE(SUCCEEDED(hr));
    
    bRet = COleObjectFactory::UpdateRegistryAll(); 
    ITypeLib * ptlib;		
    CString strPath		= "S7wmedax.exe"; //""d:\\Daten\\Source\\Siemens\\c++\\S7EDB_U_050601\\Binaries\\Win32\\Debug\\Product\\[CommonDir]\\S7WMEDB\\S7wmedax.exe";
    hr = LoadTypeLibEx(T2OLE(strPath), REGKIND_REGISTER, &ptlib);
    _ASSERTE(SUCCEEDED(hr));
    


    Tuesday, June 4, 2019 10:41 AM
  • What I mean by a description is what does your OLE server accomplish?

    Drag and drop?  Embedded OLE Documents?  Application Automation?

    These kinds of activities are designed for use in interactive applications, not Windows Services.


    Also, did you read the earlier responses regarding AfxGetClassIDFromString?
    • Edited by RLWA32 Tuesday, June 4, 2019 10:51 AM
    Tuesday, June 4, 2019 10:45 AM
  • What I mean by a description is what does your OLE server accomplish?

    Drag and drop?  Embedded OLE Documents?  Application Automation?

    These kinds of activities are designed for use in interactive applications, not Windows Services.

    That is a good question. It not my code.

    So I try to explain: The service has to open an own DB and delivers data to the OLE test application. In the OLE classes I find things like:

    • BEGIN_MESSAGE_MAP
    • BEGIN_DISPATCH_MAP with DISP_FUNCTION
    • BEGIN_INTERFACE_MAP with INTERFACE_PART
    • IMPLEMENT_OLECREATE

    Tuesday, June 4, 2019 10:55 AM
  • Run procmon and step through your code too see where it's looking up in registry.

    Registry Virtualization is enabled for 32 bit interactive applications, but disabled for 32 bit services. 



    Visual C++ MVP

    Tuesday, June 4, 2019 9:00 PM
  • My service isn't visible in procmon !
    Wednesday, June 5, 2019 1:34 PM
  • Is your service a 32 bit or 64 bit process?

    Does the service executable have a manifest?

    And the same questions for the test program.


    What account is used for the service?  For the test program?
    • Edited by RLWA32 Wednesday, June 5, 2019 1:36 PM
    Wednesday, June 5, 2019 1:36 PM
  • Service and test program are Win32 and Embeded Manifest is set to "Yes".

    I start the service in a command shell with admin rights:

    sc create "xxx" binPath= "d:\Daten\Source\Win32\xxx\Debug\xxx.exe"
    sc start "xxx"

    The test program is started via VC2010 with admin rights.

    Wednesday, June 5, 2019 1:47 PM
  • My service isn't visible in procmon !

    1) Since the call to AfxGetClassIDFromString failed from the test program that is the application you should run so that procmon can identify the associated registry activity.

    2) Procmon will log service activity based on your service executable's name, not the display name of the service.  Make sure that procmon is running before you start the service.

    3. Although you ran sc create and sc start from an elevated command prompt as an Administrator, the service itself will run under the LocalSystem account.  I suggest you check whether this account is acceptable for your DB.

    Wednesday, June 5, 2019 3:01 PM
  • BEGIN_MESSAGE_MAP implies that this is expecting to receive window messages.  Services cannot have windows.  That's one of the restrictions of being in session 0.

    Why do you want to make this a service?  What do you gain by making it a service over just a normal out-of-process server?  In both cases, you'll be started as a background process to handle requests.


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Wednesday, June 5, 2019 11:10 PM
  • Why do you want to make this a service?  What do you gain by making it a service over just a normal out-of-process server?  In both cases, you'll be started as a background process to handle requests.


    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.


    We need a service cause other tools used my tool without having users logged-in.
    Thursday, June 13, 2019 1:28 PM
  • We need a service cause other tools used my tool without having users logged-in.

    This implies that you expect your service to interact with applications running on remote systems.  Assuming that you were able to successfully create a Windows service that provided your database services through COM/OLE you would still need to configure everything to support remote access.

    Since you started this thread by saying "I am not a specialist in OLE" I suggest that you consider seeking on-site assistance from personnel with the appropriate background in the technologies being used.  In my opinion, seeking assistance only through these forums will likely be a difficult and time consuming process.

    Thursday, June 13, 2019 3:40 PM
  • Since you started this thread by saying "I am not a specialist in OLE" I suggest that you consider seeking on-site assistance from personnel with the appropriate background in the technologies being used.  In my opinion, seeking assistance only through these forums will likely be a difficult and time consuming process.

    Nice idea, but the code is very old and nobody has knowledge about this code. I won this problem! ;-)

    What have I done. I changed so original code to work without any window. It works with my ole test app. The ole init was done there in InitInstanc. Calls for ole init:
    - AfxOleInit...
    -
    CSecurityDescriptor...
    -
    COleObjectFactory::UpdateRegistryAll()
    - LoadTypeLibEx(T2OLE(strPath), REGKIND_REGISTER, &ptlib);


    The I build a service with WinMain and

    VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv);
    VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv);
    VOID WINAPI ServiceCtrlHandler (DWORD);
    DWORD WINAPI ServiceWorkerThread (LPVOID lpParam);

    the service starts and all ole init from the top is called once a time in ServiceWorkerThread without any error. But my ole test app doesn't work.

    My 1st question is:
    - Is it allowed to create a service with the basic class CWinAPI?
    - Is it possible to call Ole in such a service

    • BEGIN_MESSAGE_MAP
    • BEGIN_DISPATCH_MAP with DISP_FUNCTION
    • BEGIN_INTERFACE_MAP with INTERFACE_PART
    • IMPLEMENT_OLECREATE

    Thanks!

    Friday, June 14, 2019 10:46 AM

  • What have I done. I changed so original code to work without any window. It works with my ole test app. The ole init was done there in InitInstanc. Calls for ole init:
    - AfxOleInit...
    -
    CSecurityDescriptor...
    -
    COleObjectFactory::UpdateRegistryAll()
    - LoadTypeLibEx(T2OLE(strPath), REGKIND_REGISTER, &ptlib);


    The I build a service with WinMain and

    VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv);
    VOID WINAPI ServiceMain (DWORD argc, LPTSTR *argv);
    VOID WINAPI ServiceCtrlHandler (DWORD);
    DWORD WINAPI ServiceWorkerThread (LPVOID lpParam);

    the service starts and all ole init from the top is called once a time in ServiceWorkerThread without any error. But my ole test app doesn't work.

    My 1st question is:
    - Is it allowed to create a service with the basic class CWinAPI?
    - Is it possible to call Ole in such a service

    • BEGIN_MESSAGE_MAP
    • BEGIN_DISPATCH_MAP with DISP_FUNCTION
    • BEGIN_INTERFACE_MAP with INTERFACE_PART
    • IMPLEMENT_OLECREATE

    Thanks!

    The MFC framework is not designed to create Windows services.  So cutting and pasting code from an MFC application intended to run in an interactive session into code for a windows service is a problematic exercise.

    As Tim Roberts has already pointed out, BEGIN_MESSAGE_MAP relates to windowing.

    The framework designed to be used with COM in a windows service is ATL.

    Friday, June 14, 2019 11:00 AM
  • You have some conflicting requirements here.  If no one is logged in, then you can't do any GUI stuff anyway (even without the service restriction), so none of the window message code will work.  You may need to take a look at the service.  If you have some parts that interact with the desktop and some that don't, you may need to separate it into two components.  The non-GUI part can run as a service, and the GUI-related parts can run as a normal COM server.

    Tim Roberts | Driver MVP Emeritus | Providenza & Boekelheide, Inc.

    Friday, June 14, 2019 6:13 PM