Quote
Originally posted by herd@Aug 11 2004, 11:43 PM
Hey Siwu,
3. In a XP fast user switching one'll need to take a snapshot of user #1 desktop and stream it somehow to user #2, switch to user #2 and animate from #1 to #2
desktops, as alilm has already demoed. Maybe your toolkit provides a convenient way to do this since your driver runs with system credentials also for taking a snapshot from a hidden desktop that isn't connected to the window station:look for yourself here...
5. If not the driver, then at least the companion DLL should be open source so that users who want to provide a no-install single exe application could build it as a static library or simply verbatim copy the access code (does it need more than DeviceIOControl()?) in their apps.
/me waits excitedly for a release... 
<{POST_SNAPBACK}>
Well, for fast user switching, APIs like PrintWindow() or SPrintWindow() can't be used, since the technique that they are using for screenshoting the window require a "user" window, ie, not the desktop window.
So the toolkit doesn't provide a convenient way to share desktop screenshots.
But here's the way I think it:
the main problem for fast user switching is to copy the bitmap data from one user to another.
I think it can be done using several ways:
- use the WM_COPYDATA message
- use a dll with a shared section that could contain the bitmap pointer
- use a kernel driver, and use DeviceIOControl for copying the data, it's kinda slow, but it could work
- use a kernel driver, then allocate the bitmap in kernel memory and then share it to the different user using IoMDL.
- use a combination of HBITMAP and GDITable patching.
Let me explain in depth the different methods:
WM_COPYDATA:
this window message can copy data over different processes, so if the user 2 can find the window of the user1, WM_COPYDATA can be used to pass data between the two processes
A Dll with a shared section
the shared section of a dll loaded by both the processes can be a good way to share data
A Kernel driver with DeviceIOControl:
well, just pass the data to the kernel using the DeviceIOControl IOBuffer, and then pass it back to the other user process.
A Kernel driver with IoMDL:
kernel memory can be shared to user mode apps using MDLs. in practice, an MDL is a shared memory section that can be accessed both by the kernel and the user land.
I didn't used them much, but it returns 2 pointers: one for kernel, one for user. However I can supply you a paper with some infos on them, when using mirror drivers.
HBITMAP + GDITable patching:
GDI keeps track of its objects in a table, called GDITable. Its size is 16.384 entries and all of them system wide. So an HBITMAP from a process (of every user) is valid on another application. But if you try to print a HBITMAP in the process that didn't created it, you result in an error. Why ? because a GDITable entry is prototyped like this:
Quote
typedef struct
{
void *pKernel;
unsigned short nProcess;
unsigned short nCount;
unsigned short nUpper;
unsigned short nType;
void *pUser;
} GdiTableEntry;
See the nProcess entry ? this is actually the pid of the process which created the object. So if the process trying to use that handle isn't the process which created it, you result in an error.
However, when this value is set to 0, the handle is valid for all process (system wide). But how can it be written ?
Well, the GDITable is located on every process at the address: pGdiTable = (GdiTableEntry *)(*(LPDWORD)(0x7ffdf000 + 0x094));
But the problem is, it's not writteable from userland mode, only from kernel mode. and in kernel mode, using the debuging symbols, the gditable is called: _gpentHmgr. From kernel mode the table is writteable.
So, my solution for fast user switching would be that one:
the same program runs in user1 and user2
and a kernel driver is running (system wide)
when time to switch, the user1 instance of the program takes a screenshot of the desktop, then pass the handle to the driver.
now, the driver will modify the nProcess field of the table entry.
when user2 logs in, it asks the driver for the handle, and just have to draw it on a texture, or in a DIB (using GetBitmapBits()).
If you want I have some code that can access GDITable entries in a [] way
But if you want to know how to retrieve a GDI table entry by it's handle, here's the code:
Quote
GdiTableEntry & operator [](HGDIOBJ hHandle) const
{
return (pGdiTable[(unsigned)hHandle & 0x3FFF]);
}
0x3FFF = 16.384
a convenient class is joined to this post if you wanna give it a try
Well, if I hope you find this solution acceptable
Oh, and sorry, no, the DLL isn't just doing a DeviceIOControl, it has to configure the driver using the .spw files and some stuff I don't want to tell for the moment

But really I have to think of it lol
siwu