• Status: Solved
  • Priority: Medium
  • Security: Public
  • Views: 508
  • Last Modified:

NT Service Window Enumeration Question

I have a NT Service that is set to NOT interact with the desktop. This calls a program that I want to pass info to a window of a service process that CAN interact with the desktop. I tried  
EnumWindowStations(),
EnumDesktops(),
EnumDesktopWindows().

How can I get at all the windows on the system?  
0
AndrewR
Asked:
AndrewR
  • 9
  • 4
  • 3
1 Solution
 
chensuCommented:
I don't understand your question very well. Is EnumWindows what you are looking for?
0
 
jkrCommented:
You'll have to get access to the user's desktop. The easiest way to do this is to 'impersonate' the security context of the logged-on user using one of the user's process token. Some 'pseudocode' to illustrate it:


HANDLE GetTokenOfLoggedOnUser()
{
 HANDLE hToken;
 HANDLE hProcess;
 DWORD dwPID;
 // find PID of 'explorer.exe'
 // HOWTO: Enumerate Applications in Win32
 // http://support.microsoft.com/support/kb/articles/Q175/0/30.ASP 

    hProcess    =   OpenProcess (   PROCESS_ALL_ACCESS,
                                    TRUE,
                                    dwPID
                                );
  
    if  (   !OpenProcessToken   (   hProcess,
                                    TOKEN_QUERY,
                                    &hToken
                                )
        )   return  (   INVALID_HANDLE_VALUE);

 return ( hToken);
}

//Error checking & 'CloseHandle()' omitted for brevity ;-)


    DWORD dwThreadId;
    HWINSTA hwinstaSave;
    HDESK hdeskSave;
    HWINSTA hwinstaUser;
    HDESK hdeskUser;
    int result;
 
    /*
     * Ensure connection to service window station and desktop, and
     * save their handles.
     */
    GetDesktopWindow();
    hwinstaSave = GetProcessWindowStation();
    dwThreadId = GetCurrentThreadId();
    hdeskSave = GetThreadDesktop(dwThreadId);
 
    /*
     * Impersonate the client and connect to the User's
     * window station and desktop.
     */
    InpersonateLoggedOnUser ( GetTokenOfLoggedOnUser();
    hwinstaUser = OpenWindowStation(lpszWindowStation, FALSE, MAXIMUM_ALLOWED);
    if (hwinstaUser == NULL) {
        RevertToSelf();
        return 0;
    }
    SetProcessWindowStation(hwinstaUser);
    hdeskUser = OpenDesktop(lpszDesktop, 0, FALSE, MAXIMUM_ALLOWED);
    RevertToSelf();
    if (hdeskUser == NULL) {
        SetProcessWindowStation(hwinstaSave);
        CloseWindowStation(hwinstaUser);
        return 0;
    }
    SetThreadDesktop(hdeskUser);
 
    /*
     * Display message box (for example's sakes) or enumerate the windows
     */
    dwGuiThreadId = dwThreadId;
    result = MessageBox(NULL, lpszText, lpszTitle, fuStyle);
    dwGuiThreadId = 0;
 
    /*
     * Restore window station and desktop.
     */
    SetThreadDesktop(hdeskSave);
    SetProcessWindowStation(hwinstaSave);
    CloseDesktop(hdeskUser);
    CloseWindowStation(hwinstaUser);
 
    RevertToSelf();
}
0
 
jkrCommented:
To elaborate: You can't 'simply' acces the user's desktop, as it is a secured object. But 'ImpersonateLoggedOnUser()' provides a way to get the same credentials as the user that 'owns' the desktop, so you'll be able to access it. All you need is the access token of a process running in the context of the logged-on user, so 'OpenProcessToken()' will do the job for you...
0
Free Tool: Subnet Calculator

The subnet calculator helps you design networks by taking an IP address and network mask and returning information such as network, broadcast address, and host range.

One of a set of tools we're offering as a way of saying thank you for being a part of the community.

 
jkrCommented:
Ooops, have overseen chensu's comment...

But anyway, you cannot 'EnumWindows()' before you aren't 'connected' to the user's desktop.
0
 
chensuCommented:
So, jkr, do you mean that AndrewR wants to enumerate all the windows NT Service that is set to NOT interact with the desktop? What is another service for?
0
 
jkrCommented:
>> do you mean that AndrewR wants to enumerate all the
>>windows NT Service that is set to NOT interact with the
>>desktop?

No, the problem is to enumerate the windows on the user's desktop from a service that is not allowed to interact with the desktop...
0
 
chensuCommented:
I see.
0
 
jkrCommented:
Ooops...


    if  (   !OpenProcessToken   (   hProcess,
                                    TOKEN_QUERY,
                                    &hToken
                                )
        )   return  (   INVALID_HANDLE_VALUE);


should read


    if  (   !OpenProcessToken   (   hProcess,
                                    TOKEN_QUERY | TOKEN_IMPERSONATE,
                                    &hToken
                                )
        )   return  (   INVALID_HANDLE_VALUE);
 
0
 
AndrewRAuthor Commented:
jkr,
I will try this out.
How about the case where no one is logged on? Will I still be able to find a handle to the window of my service?
0
 
jkrCommented:
>>How about the case where no one is
>>logged on?

In this special case, things are more difficult, as the 'Logon' desktop is secured in a special way (to disallow password sniffing)...
0
 
jkrCommented:
Err, 'more difficult' means that you should obtain a token of the service that shows the window...
0
 
AndrewRAuthor Commented:
Is there any way to get a handle to the main window of a process if we know the process id? I am looking at this as another way around my problem.
0
 
jkrCommented:
Yes, there is one:

// globals
HWND  g_hwnd;

BOOL CALLBACK FindHwndFromPID( HWND hwnd, LPARAM lParam) :


HWND GetWindowFromPID ( DWORD dwProcessId)
{
 g_hwnd = NULL;
 g_nFound = 0;

 EnumWindows (  FindHwndFromPID,    ( LPARAM) dwProcessId));

 if ( g_hwnd)  
     // we found one...
     return ( g_hwnd);

 // nothing found :-(

 return (NULL);
}

BOOL CALLBACK FindHwndFromPID( HWND hwnd, LPARAM lParam)
{
    DWORD   dwPID2Find  =   ( DWORD) lParam;
    DWORD   dwPID       =   0;

    if  (   GetWindowThreadProcessId    (   hwnd,   &dwPID))
        {
            if  (   dwPID   ==  dwPID2Find)
                {
                    g_hwnd  =   hwnd

                    return  (   FALSE);
                }
        }

    return  (   TRUE);
}
0
 
AndrewRAuthor Commented:
It seems to me that the EnumProcesses()
will get all the process on the machine, but the EnumWindows() only gets the windows on a particular desktop. I am still having trouble implementing the proposed solution. I will keep at it...
0
 
jkrCommented:
>>but the EnumWindows() only gets the
>>windows on a particular desktop

That's exactly the problem. Thus,
using 'SetThreadDesktop()' and 'SetProcessWindowStation()' is necessary...
0
 
AndrewRAuthor Commented:
Thanks.
I got it to work using your suggestions.
0

Featured Post

The 14th Annual Expert Award Winners

The results are in! Meet the top members of our 2017 Expert Awards. Congratulations to all who qualified!

  • 9
  • 4
  • 3
Tackle projects and never again get stuck behind a technical roadblock.
Join Now