locked
SystemParametersInfo do not work on Windows7 when the app is a service RRS feed

  • Question

  • In a service , I wanted to change mouse settings such as swapping mouse buttons, double click time , mouse speed and so on. In the service I use the SystemParametersInfo API to do these. The API works fine on XP, but On windows 7 ,it does not work.

    For a test , I used the API in a console app on windows 7 and it works fine. So I write a console app and in the service I use the API "CreateProcessAsUser" to run the console app, unfortunately it does not work.

    How can I do when I need to change mouse settings in a service.

    Monday, September 6, 2010 7:43 AM

All replies

  • Can, you pls mention the error code?

    Also are you sure your "console app" was started  with proper user token and in the current logon session?

    http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/31bfa13d-982b-4b1a-bff3-2761ade5214f

    -Thanks,

    Sudhanshu

    Tuesday, September 7, 2010 12:09 PM
  • Thank you for your reply.

    I am sorry that I did not express the question clearly. When I call the console app in the service, CreateProcessAsUser return success. And in the console app , I use "GetUserName" , it returns "Administrator" which is assigned in the CreateProcessAsUser param. Then I call SystemParametersInfo, it also return success, but do not have effect because the mouse settings do not change.

    If I log in the desktop with user "Administrator" and double click the " console app" to run , it works fine.

     

    To add:

    And I add API "ProcessIdToSessionId" in the console app ,it shows session 0, not the user session.How can I run  the console app in the user session when the console app is called by a service.

    • Edited by kinghard Thursday, September 9, 2010 8:24 AM Add content
    Thursday, September 9, 2010 2:03 AM
  • Followed by http://social.msdn.microsoft.com/Forums/en-US/windowssecurity/thread/31bfa13d-982b-4b1a-bff3-2761ade5214f, I write codes below to test:

    In service:

       DWORD dwID = WTSGetActiveConsoleSessionId();
       WTSQueryUserToken(dwID, &hToken); 
       PROCESS_INFORMATION pi;
       STARTUPINFO si;
       ZeroMemory(&si, sizeof(STARTUPINFO));
       si.cb= sizeof(STARTUPINFO);
       si.lpDesktop = TEXT("winsta0\\default");
       CreateProcessAsUser(
          hToken,            // client's access token
          NULL,              // file to execute
          "c:\\test.exe",     // command line
          NULL,              // pointer to process SECURITY_ATTRIBUTES
          NULL,              // pointer to thread SECURITY_ATTRIBUTES
          FALSE,             // handles are not inheritable
          NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE,   // creation flags
          NULL,              // pointer to new environment block
          NULL,              // name of current directory
          &si,               // pointer to STARTUPINFO structure
          &pi                // receives information about new process
       );

    In the console app:

        GetUserName(user,&dwLength);
        ProcessIdToSessionId(GetCurrentProcessId(),&dwsessID);

    In the service : WTSGetActiveConsoleSessionId get the sessions ID is 3, User session ID , but in the console app: GetUserName  returns "System", and  ProcessIdToSessionId return the session ID is 0;

    I do not know why this happen ,is there something wrong is this code? Please give me help ,thank you.

     

    Thursday, September 9, 2010 9:57 AM
  • Yeah, I found few issues try like this

    DWORD dwID = WTSGetActiveConsoleSessionId();
    WTSQueryUserToken(dwID, &hToken); 

    // Duplicate the token

    HANDLE hTokenDup = NULL;

    DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,SecurityIdentification,TokenPrimary,&hTokenDup);

    // Create Environment Block

    LPVOID  pEnv = NULL;

    DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;

    if(CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE)

    {

           dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;

    }

    else

    {

    // Error

    }

    PROCESS_INFORMATION pi;


    ZeroMemory( &pi,sizeof(pi));

    STARTUPINFO si;
    ZeroMemory(&si, sizeof(STARTUPINFO));
    si.cb= sizeof(STARTUPINFO);
    si.lpDesktop = TEXT("winsta0\\default");

    CreateProcessAsUser(
          hTokenDup,            // client's access token
          NULL,              // file to execute
          "c:\\test.exe",     // command line
          NULL,              // pointer to process SECURITY_ATTRIBUTES
          NULL,              // pointer to thread SECURITY_ATTRIBUTES
          FALSE,             // handles are not inheritable
          dwCreationFlag ,   // creation flags
          pEnv,              // pointer to new environment block
          NULL,              // name of current directory
          &si,               // pointer to STARTUPINFO structure
          &pi                // receives information about new process
       );

    Thursday, September 9, 2010 4:56 PM
  • Hi sudhanshu_juyal,

        I do as you say and my code is below, but Users Medals Users Medals the result does not change:

          In the service : WTSGetActiveConsoleSessionId get the sessions ID is 3, User session ID , but in the console app:  GetUserName  returns "System", and  ProcessIdToSessionId return the session ID is 0;

    Is there someone who knows why? I really need you help.

     

        ////Code

        HANDLE hToken = NULL;
        DWORD dwID = WTSGetActiveConsoleSessionId();
        WTSQueryUserToken(dwID, &hToken);
        HANDLE hTokenDup = NULL;
        DuplicateTokenEx(hToken,MAXIMUM_ALLOWED,NULL,
        SecurityIdentification,TokenPrimary,&hTokenDup);
        LPVOID  pEnv = NULL;
        DWORD dwCreationFlag = NORMAL_PRIORITY_CLASS | CREATE_NEW_CONSOLE;
        if(CreateEnvironmentBlock(&pEnv, hTokenDup, FALSE)){
              dwCreationFlag |= CREATE_UNICODE_ENVIRONMENT;
        }
        PROCESS_INFORMATION pi;
        STARTUPINFO si;
        ZeroMemory(&si, sizeof(STARTUPINFO));
        si.cb= sizeof(STARTUPINFO);
        si.lpDesktop = TEXT("winsta0\\default");

    // Launch the process in the client's logon session.
        CreateProcessAsUser(
          hTokenDup,            // client's access token
          NULL,              // file to execute
          "z:\\test.exe",     // command line
          NULL,              // pointer to process SECURITY_ATTRIBUTES
          NULL,              // pointer to thread SECURITY_ATTRIBUTES
          FALSE,             // handles are not inheritable
          dwCreationFlag,   // creation flags
          pEnv,              // pointer to new environment block
          NULL,              // name of current directory
          &si,               // pointer to STARTUPINFO structure
          &pi                // receives information about new process
       );

     

    Wednesday, September 15, 2010 6:44 AM
  • Is your service started before you login to the system ie at boot time?

    -Sudhanshu

    Thursday, September 16, 2010 4:40 AM
  • And also is your test.exe is started before you login ie when your service starts ?
    Thursday, September 16, 2010 4:42 AM
  • Thank you, Sudhanshu

     

    My service startup type  is automatic and how can I know whether the service started before I login to the system ie at

    boot time or not.

     

    When service starts ,it does not run test.exe . After I log on to the desktop of  Administrator, I use a console in another

    computer to give the service a message by TCP/IP to run test.exe.

    Thursday, September 16, 2010 8:46 AM
  • One point to clear:

    In my service ,  I call another process, in this process ,  I use CreateProcessAsUser to call the test.exe.

    Now, I find that if I use CreateProcessAsUser in the service process, it works fine. But if I use CreateProcessAsUser in the process created by service , it does not

    work.

    the codes of process created by service is as below:

        si.dwFlags = STARTF_USESHOWWINDOW;
        si.wShowWindow = SW_HIDE;

        if (FALSE == CreateProcess(
            NULL, A2T(pCmd),
            NULL, NULL, TRUE,
            CREATE_NEW_CONSOLE,
            NULL, NULL,   
            &si, &pi))
            return false;

    Is there something wrong and what need to do when create this process.

     

    Sunday, September 19, 2010 7:38 AM
  • Hi,

    Thats the most important point you were missing earlier.

    Why are you using CreateProcess API, this will start your process in service session which is session 0.

    Can you use CreateProcessAsUser to start your Process A from service. And then use CreateProcess API to start Process B from Process A.

    - Sudhanshu

    Monday, September 20, 2010 7:16 AM
  • Hi Sudhanshu,

    Thank you very much.

    But I have a question:as you say ,the process created by service using CreateProcess is in session 0 , but the service is also in session 0. Why service can work fine

    but the process created by service can not.

    Thanks,

    King

    Monday, September 20, 2010 7:27 AM
  • After duplicating the token you have to make a call to set the session id of the gathered token. The additional call I think you have to make from your process.

    SetTokenInformation(hTokenDup, TokenSessionId, (void*)dwID,
            sizeof(DWORD));

     

    Tuesday, September 21, 2010 2:05 PM