Microsoft KB Archive/173687

{|
 * width="100%"|

HOWTO: Access the Application Desktop from a Service

 * }

Q173687

-

The information in this article applies to:


 * Microsoft Win32 Application Programming Interface (API), used with:
 * the operating system: Microsoft Windows NT, versions 3.51, 4.0
 * the operating system: Microsoft Windows 2000

-

SUMMARY
The configuration of a Windows NT service determines how it may access the application desktop. The application desktop is named "default" and belongs to the "WinSta0" Window station object. The application desktop is associated with the interactively logged-on user. A process that has access to the application desktop can display message boxes, windows, and dialog boxes that can be seen visually by the interactively logged-on user. In addition, a process with access to the application desktop can send messages to other processes running on the desktop. The application desktop is not destroyed when the interactively logged-on user logs off.

NOTE: Running interactive services under the LocalSystem account is a VERY dangerous practice. This is especially true of the command processor and batch files. A user who wants to control the system can just hit CTRL+C to get an interactive system command prompt.

MORE INFORMATION
A service that is configured in the LocalSystem account and is interacting with the desktop (the service type includes the SERVICE_INTERACTIVE_PROCESS flag) has access to the application desktop.

A service that is configured in the LocalSystem account and is not interacting with the desktop does not have access to the application desktop by default. If the service needs to display information through a message box, you can do this by specifying one of the following two flag types:

  MB_DEFAULT_DESKTOP_ONLY - The message box will appear on the application desktop, for example, "winsta0\default". MB_SERVICE_NOTIFICATION - The message box will appear on the currently active desktop. In addition, a service configured in the LocalSystem account can reconfigure its thread to access the application desktop. This is demonstrated in the following sample code. The sample code obtains handles to the "WinSta0" window station and the "default" desktop. Then it re- associates the current thread to the application desktop. Then the sample will display a message box and, when access to the interactive desktop is no longer needed, it resets the thread to the original window station and desktop. This must be done for every thread that wants access to the application desktop.

Sample Code
  BOOL ThreadInteract(void) {     HDESK   hdeskCurrent; HDESK  hdesk; HWINSTA hwinstaCurrent; HWINSTA hwinsta;

//      // Save the current Window station //      hwinstaCurrent = GetProcessWindowStation; if (hwinstaCurrent == NULL) return FALSE;

//      // Save the current desktop //      hdeskCurrent = GetThreadDesktop(GetCurrentThreadId); if (hdeskCurrent == NULL) return FALSE;

//      // Obtain a handle to WinSta0 - service must be running // in the LocalSystem account //      hwinsta = OpenWindowStation("winsta0", FALSE,                                  WINSTA_ACCESSCLIPBOARD   |                                  WINSTA_ACCESSGLOBALATOMS |                                  WINSTA_CREATEDESKTOP     |                                  WINSTA_ENUMDESKTOPS      |                                  WINSTA_ENUMERATE         |                                  WINSTA_EXITWINDOWS       |                                  WINSTA_READATTRIBUTES    |                                  WINSTA_READSCREEN        |                                  WINSTA_WRITEATTRIBUTES); if (hwinsta == NULL) return FALSE;

//      // Set the windowstation to be winsta0 //      if (!SetProcessWindowStation(hwinsta)) return FALSE;

//      // Get the default desktop on winsta0 //      hdesk = OpenDesktop("default", 0, FALSE,                            DESKTOP_CREATEMENU |                  DESKTOP_CREATEWINDOW |                            DESKTOP_ENUMERATE    |                            DESKTOP_HOOKCONTROL  |                            DESKTOP_JOURNALPLAYBACK |                            DESKTOP_JOURNALRECORD |                            DESKTOP_READOBJECTS |                            DESKTOP_SWITCHDESKTOP |                            DESKTOP_WRITEOBJECTS); if (hdesk == NULL) return FALSE;

//   // Set the desktop to be "default" //   if (!SetThreadDesktop(hdesk)) return FALSE;

//   // Do a message box //   MessageBox(NULL, "MB_OK", "test_interact", MB_OK);

//   // Reset the Window station and desktop //   if (!SetProcessWindowStation(hwinstaCurrent)) return FALSE;

if (!SetThreadDesktop(hdeskCurrent)) return FALSE;

//   // Close the windowstation and desktop handles //   if (!CloseWindowStation(hwinsta)) return FALSE;

if (!CloseDesktop(hdesk)) return FALSE;

return TRUE; } A service configured for a user account can access the application desktop through the message box types mentioned above. The above code will fail for a service configured for a user account due to security reasons but it will work for a service that impersonates the interactively logged-on user. For example, impersonation can be done through a named pipe connection from a process running on the application desktop. The service would have to impersonate the named pipe client.

Additional query words:

Keywords : kbKernBase kbOSWin2000 kbSecurity kbService kbDSupport kbGrpDSKernBase

Issue type : kbhowto

Technology : kbAudDeveloper kbWin32sSearch kbWin32API