user: Tests for when the menu is incorrect because of duplication of a
[wine] / dlls / user / tests / winstation.c
1 /*
2  * Unit tests for window stations and desktops
3  *
4  * Copyright 2002 Alexandre Julliard
5  *
6  * This library is free software; you can redistribute it and/or
7  * modify it under the terms of the GNU Lesser General Public
8  * License as published by the Free Software Foundation; either
9  * version 2.1 of the License, or (at your option) any later version.
10  *
11  * This library is distributed in the hope that it will be useful,
12  * but WITHOUT ANY WARRANTY; without even the implied warranty of
13  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
14  * Lesser General Public License for more details.
15  *
16  * You should have received a copy of the GNU Lesser General Public
17  * License along with this library; if not, write to the Free Software
18  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
19  */
20
21 #include "wine/test.h"
22 #include "winbase.h"
23 #include "wingdi.h"
24 #include "winuser.h"
25
26 #define DESKTOP_ALL_ACCESS 0x01ff
27
28 static void print_object( HANDLE obj )
29 {
30     char buffer[100];
31     DWORD size;
32
33     strcpy( buffer, "foobar" );
34     if (!GetUserObjectInformationA( obj, UOI_NAME, buffer, sizeof(buffer), &size ))
35         trace( "could not get info for %p\n", obj );
36     else
37         trace( "obj %p name '%s'\n", obj, buffer );
38     strcpy( buffer, "foobar" );
39     if (!GetUserObjectInformationA( obj, UOI_TYPE, buffer, sizeof(buffer), &size ))
40         trace( "could not get type for %p\n", obj );
41     else
42         trace( "obj %p type '%s'\n", obj, buffer );
43 }
44
45 static HDESK initial_desktop;
46
47 static DWORD CALLBACK thread( LPVOID arg )
48 {
49     HDESK d1, d2;
50     HWND hwnd = CreateWindowExA(0,"BUTTON","test",WS_POPUP,0,0,100,100,GetDesktopWindow(),0,0,0);
51     ok( hwnd != 0, "CreateWindow failed\n" );
52     d1 = GetThreadDesktop(GetCurrentThreadId());
53     trace( "thread %p desktop: %p\n", arg, d1 );
54     ok( d1 == initial_desktop, "thread %p doesn't use initial desktop\n", arg );
55
56     SetLastError( 0xdeadbeef );
57     ok( !CloseHandle( d1 ), "CloseHandle succeeded\n" );
58     ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
59     SetLastError( 0xdeadbeef );
60     ok( !CloseDesktop( d1 ), "CloseDesktop succeeded\n" );
61     ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() );
62     print_object( d1 );
63     d2 = CreateDesktop( "foobar2", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
64     trace( "created desktop %p\n", d2 );
65     ok( d2 != 0, "CreateDesktop failed\n" );
66
67     SetLastError( 0xdeadbeef );
68     ok( !SetThreadDesktop( d2 ), "set thread desktop succeeded with existing window\n" );
69     ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() );
70
71     DestroyWindow( hwnd );
72     ok( SetThreadDesktop( d2 ), "set thread desktop failed\n" );
73     d1 = GetThreadDesktop(GetCurrentThreadId());
74     ok( d1 == d2, "GetThreadDesktop did not return set desktop %p/%p\n", d1, d2 );
75     print_object( d2 );
76     if (arg < (LPVOID)5)
77     {
78         HANDLE hthread = CreateThread( NULL, 0, thread, (char *)arg + 1, 0, NULL );
79         Sleep(1000);
80         WaitForSingleObject( hthread, INFINITE );
81         CloseHandle( hthread );
82     }
83     return 0;
84 }
85
86 static void test_handles(void)
87 {
88     HWINSTA w1, w2, w3;
89     HDESK d1, d2, d3;
90     HANDLE hthread;
91     DWORD id, flags;
92
93     /* win stations */
94
95     w1 = GetProcessWindowStation();
96     ok( GetProcessWindowStation() == w1, "GetProcessWindowStation returned different handles\n" );
97     ok( !CloseWindowStation(w1), "closing process win station succeeded\n" );
98     SetLastError( 0xdeadbeef );
99     ok( !CloseHandle(w1), "closing process win station handle succeeded\n" );
100     ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
101     print_object( w1 );
102
103     flags = 0;
104     ok( GetHandleInformation( w1, &flags ), "GetHandleInformation failed\n" );
105     ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", w1 );
106
107     ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0,
108                          TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
109     ok( CloseWindowStation(w2), "closing dup win station failed\n" );
110
111     ok( DuplicateHandle( GetCurrentProcess(), w1, GetCurrentProcess(), (PHANDLE)&w2, 0,
112                          TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
113     ok( CloseHandle(w2), "closing dup win station handle failed\n" );
114
115     w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
116     ok( w2 != 0, "CreateWindowStation failed\n" );
117     ok( w2 != w1, "CreateWindowStation returned default handle\n" );
118     SetLastError( 0xdeadbeef );
119     ok( !CloseDesktop( (HDESK)w2 ), "CloseDesktop succeeded on win station\n" );
120     ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
121     ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
122
123     w2 = CreateWindowStation("WinSta0", 0, WINSTA_ALL_ACCESS, NULL );
124     ok( CloseHandle( w2 ), "CloseHandle failed\n" );
125
126     w2 = OpenWindowStation("winsta0", TRUE, WINSTA_ALL_ACCESS );
127     ok( w2 != 0, "OpenWindowStation failed\n" );
128     ok( w2 != w1, "OpenWindowStation returned default handle\n" );
129     ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
130
131     w2 = OpenWindowStation("dummy name", TRUE, WINSTA_ALL_ACCESS );
132     ok( !w2, "open dummy win station succeeded\n" );
133
134     CreateMutexA( NULL, 0, "foobar" );
135     w2 = CreateWindowStation("foobar", 0, WINSTA_ALL_ACCESS, NULL );
136     ok( w2 != 0, "create foobar station failed\n" );
137
138     w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS );
139     ok( w3 != 0, "open foobar station failed\n" );
140     ok( w3 != w2, "open foobar station returned same handle\n" );
141     ok( CloseWindowStation( w2 ), "CloseWindowStation failed\n" );
142     ok( CloseWindowStation( w3 ), "CloseWindowStation failed\n" );
143
144     w3 = OpenWindowStation("foobar", TRUE, WINSTA_ALL_ACCESS );
145     ok( !w3, "open foobar station succeeded\n" );
146
147     /* desktops */
148     d1 = GetThreadDesktop(GetCurrentThreadId());
149     initial_desktop = d1;
150     ok( GetThreadDesktop(GetCurrentThreadId()) == d1,
151         "GetThreadDesktop returned different handles\n" );
152
153     flags = 0;
154     ok( GetHandleInformation( d1, &flags ), "GetHandleInformation failed\n" );
155     ok( !(flags & HANDLE_FLAG_PROTECT_FROM_CLOSE), "handle %p PROTECT_FROM_CLOSE set\n", d1 );
156
157     SetLastError( 0xdeadbeef );
158     ok( !CloseDesktop(d1), "closing thread desktop succeeded\n" );
159     ok( GetLastError() == ERROR_BUSY, "bad last error %ld\n", GetLastError() );
160
161     SetLastError( 0xdeadbeef );
162     ok( !CloseHandle(d1), "closing thread desktop handle failed\n" );
163     ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
164
165     ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0,
166                          TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
167     ok( CloseDesktop(d2), "closing dup desktop failed\n" );
168
169     ok( DuplicateHandle( GetCurrentProcess(), d1, GetCurrentProcess(), (PHANDLE)&d2, 0,
170                          TRUE, DUPLICATE_SAME_ACCESS ), "DuplicateHandle failed\n" );
171     ok( CloseHandle(d2), "closing dup desktop handle failed\n" );
172
173     d2 = OpenDesktop( "dummy name", 0, TRUE, DESKTOP_ALL_ACCESS );
174     ok( !d2, "open dummy desktop succeeded\n" );
175
176     d2 = CreateDesktop( "foobar", NULL, NULL, 0, DESKTOP_ALL_ACCESS, NULL );
177     ok( d2 != 0, "create foobar desktop failed\n" );
178     SetLastError( 0xdeadbeef );
179     ok( !CloseWindowStation( (HWINSTA)d2 ), "CloseWindowStation succeeded on desktop\n" );
180     ok( GetLastError() == ERROR_INVALID_HANDLE, "bad last error %ld\n", GetLastError() );
181
182     d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
183     ok( d3 != 0, "open foobar desktop failed\n" );
184     ok( d3 != d2, "open foobar desktop returned same handle\n" );
185     ok( CloseDesktop( d2 ), "CloseDesktop failed\n" );
186     ok( CloseDesktop( d3 ), "CloseDesktop failed\n" );
187
188     d3 = OpenDesktop( "foobar", 0, TRUE, DESKTOP_ALL_ACCESS );
189     ok( !d3, "open foobar desktop succeeded\n" );
190
191     ok( !CloseHandle(d1), "closing thread desktop handle succeeded\n" );
192     d2 = GetThreadDesktop(GetCurrentThreadId());
193     ok( d1 == d2, "got different handles after close\n" );
194
195     trace( "thread 1 desktop: %p\n", d1 );
196     print_object( d1 );
197     hthread = CreateThread( NULL, 0, thread, (LPVOID)2, 0, &id );
198     Sleep(1000);
199     trace( "get other thread desktop: %p\n", GetThreadDesktop(id) );
200     WaitForSingleObject( hthread, INFINITE );
201     CloseHandle( hthread );
202 }
203
204 START_TEST(winstation)
205 {
206     /* Check whether this platform supports WindowStation calls */
207
208     SetLastError( 0xdeadbeef );
209     GetProcessWindowStation();
210     if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
211     {
212         trace("WindowStation calls not supported on this platform\n");
213         return;
214     }
215
216     test_handles();
217 }