Windows Stations and Desktops in General

Started by
12 comments, last by adeyblue 14 years, 11 months ago
Well hello again guys, my second thread here. I recently decided that I would like to create my own virtual desktop program (like Cube DeskTop or something). I've done quite a lot of research and found that there are three desktops that the computer starts of with; Winlogon, Default and Screensaver. I started off knowing nothing, but now I know a few things and am doing some tests, such as how to enumerate through all the desktops. But I've already run into a little snag... for some reason my program only tells me that there is the Default desktop and says nothing about the Winlogon or screensaver desktops, why is that?

#include <windows.h>

#define TEST MessageBox(MainWindow, "Success.", "Report", MB_OK);
#define DesktopsList 1001
#define DesktopSearch 1002

HINSTANCE hInstance = NULL;

HDESK TempDesk = NULL;

HWND MainWindow     = NULL;
HWND DesktopsListLB = NULL;
HWND DesktopSearchB = NULL;

BOOL CALLBACK DesktopSearchProc(LPTSTR DesktopName, LPARAM lParam);
LRESULT CALLBACK MainWNDProc(HWND MainWindow, UINT Msg, WPARAM wParam, LPARAM lParam);

INT WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, INT nShowCmd)
{

 WNDCLASSEX WNDClass;
 MSG Msg;

 ZeroMemory(&WNDClass, sizeof(WNDClass));

 WNDClass.cbSize = sizeof(WNDClass);
 WNDClass.style = CS_HREDRAW | CS_VREDRAW;
 WNDClass.hbrBackground = GetSysColorBrush(COLOR_3DFACE);
 WNDClass.hCursor = LoadCursor(NULL, IDC_ARROW);
 WNDClass.hIcon = LoadIcon(NULL, IDI_APPLICATION);
 WNDClass.hIconSm = LoadIcon(NULL, IDI_APPLICATION);
 WNDClass.hInstance = hInstance;
 WNDClass.lpfnWndProc = MainWNDProc;
 WNDClass.lpszClassName = "MainWNDClass";

 RegisterClassEx(&WNDClass);

 MainWindow = CreateWindowEx(NULL, WNDClass.lpszClassName, "Welcome", WS_VISIBLE | WS_OVERLAPPED | WS_MINIMIZEBOX | WS_SYSMENU | WS_CAPTION, CW_USEDEFAULT, CW_USEDEFAULT, 233, 480, NULL, NULL, hInstance, NULL);

 ShowWindow(MainWindow, nShowCmd);
 UpdateWindow(MainWindow);

 while(GetMessage(&Msg, NULL, NULL, NULL) > 0)
 {

  TranslateMessage(&Msg);
  DispatchMessage(&Msg);

 }

 return Msg.wParam;

}

BOOL CALLBACK DesktopSearchProc(LPTSTR DesktopName, LPARAM lParam)
{

 SendMessage(DesktopsListLB, LB_ADDSTRING, NULL, (LPARAM)DesktopName);

 return TRUE;

}

LRESULT CALLBACK MainWNDProc(HWND MainWindow, UINT Msg, WPARAM wParam, LPARAM lParam)
{

 switch(Msg)
 {

  case WM_CREATE:

   DesktopsListLB = CreateWindowEx(NULL, "LISTBOX", "DesktopsListLB", WS_CHILD | WS_VISIBLE | LBS_STANDARD, 15, 12, 200, 100, MainWindow, (HMENU)DesktopsList, hInstance, NULL);
   DesktopSearchB = CreateWindowEx(NULL, "BUTTON", "Search for Desktops", WS_CHILD | WS_VISIBLE | BS_PUSHBUTTON, 15, 118, 200, 20, MainWindow, (HMENU)DesktopSearch, hInstance, NULL);

   //TempDesk = CreateDesktop("TempDesk", NULL, NULL, NULL, DESKTOP_CREATEMENU | DESKTOP_CREATEWINDOW | DESKTOP_ENUMERATE | DESKTOP_HOOKCONTROL | DESKTOP_JOURNALPLAYBACK | DESKTOP_JOURNALRECORD | DESKTOP_READOBJECTS | DESKTOP_SWITCHDESKTOP | DESKTOP_WRITEOBJECTS, NULL);

   //SwitchDesktop(TempDesk);

  break;

  case WM_COMMAND:

   switch(LOWORD(wParam))
   {

    case DesktopSearch:

     while(SendMessage(DesktopsListLB, LB_GETCOUNT, NULL, NULL) != 0) SendMessage(DesktopsListLB, LB_DELETESTRING, NULL, NULL);
 
     EnumDesktops(GetProcessWindowStation(), DesktopSearchProc, NULL);

    break;

   }

  break;

  case WM_CLOSE:

   DestroyWindow(MainWindow);

  break;

  case WM_DESTROY:

   PostQuitMessage(WM_QUIT); 

  break;

  default: return DefWindowProc(MainWindow, Msg, wParam, lParam);

 }

 return 0;

}


Thank you very much. EDIT - If possible, please recommend me any book that has information on this subject, I've tries so hard but failed to find any book that matched the following criteria: C++, Win32, Windows Stations and Desktops. Of course MSDN does have information regarding this but it doesn't have all my answers which is why I'm somewhat desperate for a book.
Advertisement
It sounds like your application does not have the rights to enumerate those desktops. Having said that, if you want a virtual desktop manager using actual Windows desktops is going to be a bad move. Switching between desktop objects is very expensive: for example, you know that long wait when UAC is activated on Vista? That wait is mainly from the switch to the secure desktop.

Instead you probably just want to make clever use of ShowWindow() with SW_HIDE. If you remember XP's virtual desktop manager powertoy, this is what it used.
Hmm, so am I right in assuming that the "Default" desktop does not have the DESKTOP_ENUMERATE right? or something (sorry for the un-professional term but I don't completely understand what I'm dealing with :D). Well I don't plan to switch between the default 3 Windows desktops, I'll create my own and use them instead.

Thank you for telling me where the delay came from, I was curious :). If I have anoy more questions later I will post.

EDIT - I just remembered that I created another desktop just for testing purposes, then while in the new desktop I pressed CTRL+ALT+DELETE and got the task manager, I could see the programs running from the other "Default" desktop but not on the active desktop (the one I created), why is this? is it to do with the Windows Station or something?

Thanks again.
Oh yeahh another thing. In my program I create a new desktop that's called "TempDesktop" but don't switch to it. I then click the button that enumerates through the desktops and surely enough it finds "Default" and "TempDesktop" but when I close the program and open it again and then click Search... I still get "Default" and "TempDesktop"... shouldn't I get "Default" and 2 desktops called "TempDesktop"? I also tried changing the name to "TempDesktop2" and still when I re-start the program only those two desktops are detected. Are desktops created by a program automatically destroyed upon the program exiting?
Quote:
I close the program and open it again and then click Search... I still get "Default" and "TempDesktop"... shouldn't I get "Default" and 2 desktops called "TempDesktop"?

No, it re-opens the one created when you first ran the program. Desktops are destroyed when the associated Windowstation is, until then, it just hangs around. The second time you run your program, Windows goes "Something with this name already exists so you must want that one." and gives you it.

Quote:
I also tried changing the name to "TempDesktop2" and still when I re-start the program only those two desktops are detected.

The first step to answering this is the same as every other "Why isn't <windows function> working?", check GetLastError when the function fails and see what it tells you. Probably out-of-memory, but who knows.
Thanks for the answer my friend :).

Hmm I see, so if a desktop named "TempDesktop" already exists and I try to create another desktop with the same name I get the handle to a already existing desktop? OK that makes sense, but wouldn't that give the same as result OpenDesktop()?

I'm pretty sure it wasn't to do with memory... as I have 4 Gigabytes of it :D. The desktop was in deed created and I know this because the procedure that searches for desktops reports that it exists. What I was trying to say was, when I compile the code with the name of the new desktop being "TempDesktop" and then close the program to change the name of the desktop to "TempDesktop2" and then recompile, why is it that my program only shows "TempDesktop2" and not "TempDesktop2" and "TempDesktop"? I am asking this because you said that the handles still exist after my program has been closed yet my program doesn't pick up the first desktop I created, and it should regardless of whether or not I have the handle because it searches for them.

Thanks again :).
Quote:Original post by VirtualProgrammer
Hmm, so am I right in assuming that the "Default" desktop does not have the DESKTOP_ENUMERATE right?

I'm no expert at desktops so I dont know. It might also be that perhaps those desktops do not allow themselves to be enumerated.

Quote:Original post by VirtualProgrammer
EDIT - I just remembered that I created another desktop just for testing purposes, then while in the new desktop I pressed CTRL+ALT+DELETE and got the task manager, I could see the programs running from the other "Default" desktop but not on the active desktop (the one I created), why is this? is it to do with the Windows Station or something?

If I understand what you did and if I understand what the task manager reports, I do not believe the task manager reports any application besides those running on the current desktop.

Quote:Original post by VirtualProgrammer
Hmm I see, so if a desktop named "TempDesktop" already exists and I try to create another desktop with the same name I get the handle to a already existing desktop? OK that makes sense, but wouldn't that give the same as result OpenDesktop()?

Most Open*() functions in the Win32 API only differ from the Create*() functions in that the Open*() functions fail if the object does not already exist.
Thank you for your clear answering of my questions :).

Quote:I'm no expert at desktops so I dont know. It might also be that perhaps those desktops do not allow themselves to be enumerated.

Does this mean that it is impossible for any program to detect a desktop if the desktop does not have the DESKTOP_ENUMERATE style? Hmm, when you set the types of access allowed to a soon to be created desktop (in CreateDesktop(), for example DESKTOP_ENUMERATE or DESKTOP_SWITCH) what do those access types apply to? Is it my program or every other program or both? I'm sorry if I don't make sense here, I can't seem to say it in a better way right now :(.

Quote:If I understand what you did and if I understand what the task manager reports, I do not believe the task manager reports any application besides those running on the current desktop.

In the new desktop that I created and switched to ("TempDesktop") I did definatly see the programs running in the other desktop, but when I clicked "Switch To" or "End Task" or when I right-clicked a program and clicked on "Go to process" nothing happened, but if I went to the processes tab and chose to terminate a process by force it worked.

Quote:Most Open*() functions in the Win32 API only differ from the Create*() functions in that the Open*() functions fail if the object does not already exist.

Well alright then this made complete sense :).

Thanks for all your help!
Quote:Original post by VirtualProgrammer
Does this mean that it is impossible for any program to detect a desktop if the desktop does not have the DESKTOP_ENUMERATE style? Hmm, when you set the types of access allowed to a soon to be created desktop (in CreateDesktop(), for example DESKTOP_ENUMERATE or DESKTOP_SWITCH) what do those access types apply to? Is it my program or every other program or both?


Every object in Windows has an associated list of accounts and permissions. If that list has an entry for your account and it includes DESKTOP_ENUMERATE, then you can enumerate it, otherwise you can't. Those flags you pass in to CreateDesktop (and every other Create* function) determine the operations you can perform on that instance. If you include DESKTOP_SWITCH for instance you'll be able to switch to it, else you won't, even if you have permission to. The last argument lets you assign a custom list of accounts and permissions to the object if you so desire, otherwise you get a default one.

Quote:
In the new desktop that I created and switched to ("TempDesktop") I did definatly see the programs running in the other desktop, but when I clicked "Switch To" or "End Task" or when I right-clicked a program and clicked on "Go to process" nothing happened, but if I went to the processes tab and chose to terminate a process by force it worked.

Seems like Task Manager can't (or won't) switch desktops. And since windows are bound to a single desktop it can't move that, so it does nothing. You can terminate the process since it's just a process like any other, desktops don't come into it.
Quote:Every object in Windows has an associated list of accounts and permissions. If that list has an entry for your account and it includes DESKTOP_ENUMERATE, then you can enumerate it, otherwise you can't. Those flags you pass in to CreateDesktop (and every other Create* function) determine the operations you can perform on that instance. If you include DESKTOP_SWITCH for instance you'll be able to switch to it, else you won't, even if you have permission to. The last argument lets you assign a custom list of accounts and permissions to the object if you so desire, otherwise you get a default one.

Hmm I see... but for what reason wouldn't you want full access to a desktop that you created? Also how do I see the list of accounts and permissions?

Quote:Seems like Task Manager can't (or won't) switch desktops. And since windows are bound to a single desktop it can't move that, so it does nothing. You can terminate the process since it's just a process like any other, desktops don't come into it.

How is it that the Task Manager can even see the windows running in the "Default" desktop while I'm in the one I created? I thought desktops were completely secluded from one another. I also read that it is impossible for a program to communicate with a program in another desktop. But say I really need to switch some information with the program, what would be the best way to communicate with my program running in the other desktop? One idea that comes to mind is to not use SendMessage() or any of its sister functions becuase they are useless but rather to use files and the registry (I could update information in the files or registry (depending on what I choose) and then have the other instance of my program periodically search for changes and respond.

Thank you and sorry if I'm overloading you with questions. Its just that I want to get everything down about Window Stations and Desktops because information seems scarce... no EBook seems to even mention anything about creating an managing anything like this. Thanks again!

This topic is closed to new replies.

Advertisement