winstation.c 13.3 KB
Newer Older
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17
/*
 * Window stations and desktops
 *
 * Copyright 2002 Alexandre Julliard
 *
 * This library is free software; you can redistribute it and/or
 * modify it under the terms of the GNU Lesser General Public
 * License as published by the Free Software Foundation; either
 * version 2.1 of the License, or (at your option) any later version.
 *
 * This library is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * Lesser General Public License for more details.
 *
 * You should have received a copy of the GNU Lesser General Public
 * License along with this library; if not, write to the Free Software
18
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
19 20
 */

21 22 23
#include "ntstatus.h"
#define WIN32_NO_STATUS

24 25 26 27 28 29 30
#include <stdarg.h>
#include "windef.h"
#include "winbase.h"
#include "winnls.h"
#include "winerror.h"
#include "wingdi.h"
#include "winuser.h"
31 32
#include "winternl.h"
#include "ddk/wdm.h"
33 34
#include "wine/server.h"
#include "wine/debug.h"
35
#include "user_private.h"
36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56

WINE_DEFAULT_DEBUG_CHANNEL(winstation);


/* callback for enumeration functions */
struct enum_proc_lparam
{
    NAMEENUMPROCA func;
    LPARAM        lparam;
};

static BOOL CALLBACK enum_names_WtoA( LPWSTR name, LPARAM lparam )
{
    struct enum_proc_lparam *data = (struct enum_proc_lparam *)lparam;
    char buffer[MAX_PATH];

    if (!WideCharToMultiByte( CP_ACP, 0, name, -1, buffer, sizeof(buffer), NULL, NULL ))
        return FALSE;
    return data->func( buffer, data->lparam );
}

57 58 59 60
/* return a handle to the directory where window station objects are created */
static HANDLE get_winstations_dir_handle(void)
{
    static HANDLE handle = NULL;
61
    WCHAR buffer[64];
62 63 64 65 66 67 68
    UNICODE_STRING str;
    OBJECT_ATTRIBUTES attr;

    if (!handle)
    {
        HANDLE dir;

69
        swprintf( buffer, ARRAY_SIZE(buffer), L"\\Sessions\\%u\\Windows\\WindowStations", NtCurrentTeb()->Peb->SessionId );
70
        RtlInitUnicodeString( &str, buffer );
71 72 73 74 75 76 77
        InitializeObjectAttributes( &attr, &str, 0, 0, NULL );
        NtOpenDirectoryObject( &dir, DIRECTORY_CREATE_OBJECT | DIRECTORY_TRAVERSE, &attr );
        if (InterlockedCompareExchangePointer( &handle, dir, 0 ) != 0) /* someone beat us here */
            CloseHandle( dir );
    }
    return handle;
}
78

79 80
static WCHAR default_name[29];

81 82 83 84 85 86 87
static BOOL WINAPI winstation_default_name_once( INIT_ONCE *once, void *param, void **context )
{
    TOKEN_STATISTICS stats;
    BOOL ret;

    ret = GetTokenInformation( GetCurrentProcessToken(), TokenStatistics, &stats, sizeof(stats), NULL );
    if (ret)
88
        swprintf( default_name, ARRAY_SIZE(default_name), L"Service-0x%x-%x$",
89
                  stats.AuthenticationId.HighPart, stats.AuthenticationId.LowPart );
90 91 92 93 94 95 96 97 98

    return ret;
}

static const WCHAR *get_winstation_default_name( void )
{
    static INIT_ONCE once = INIT_ONCE_STATIC_INIT;
    BOOL ret;

99 100
    ret = InitOnceExecuteOnce( &once, winstation_default_name_once, NULL, NULL );
    return ret ? default_name : NULL;
101 102
}

103 104 105
/***********************************************************************
 *              CreateWindowStationA  (USER32.@)
 */
106
HWINSTA WINAPI CreateWindowStationA( LPCSTR name, DWORD flags, ACCESS_MASK access,
107 108 109 110
                                     LPSECURITY_ATTRIBUTES sa )
{
    WCHAR buffer[MAX_PATH];

111
    if (!name) return CreateWindowStationW( NULL, flags, access, sa );
112 113 114 115 116 117

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
118
    return CreateWindowStationW( buffer, flags, access, sa );
119 120 121 122 123 124
}


/***********************************************************************
 *              CreateWindowStationW  (USER32.@)
 */
125
HWINSTA WINAPI CreateWindowStationW( LPCWSTR name, DWORD flags, ACCESS_MASK access,
126 127
                                     LPSECURITY_ATTRIBUTES sa )
{
128 129
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING str;
130

131 132 133 134 135 136 137 138 139
    RtlInitUnicodeString( &str, name );
    if (!str.Length) RtlInitUnicodeString( &str, get_winstation_default_name() );

    InitializeObjectAttributes( &attr, &str, OBJ_CASE_INSENSITIVE,
                                get_winstations_dir_handle(), sa );
    if (!(flags & CWF_CREATE_ONLY)) attr.Attributes |= OBJ_OPENIF;
    if (sa && sa->bInheritHandle) attr.Attributes |= OBJ_INHERIT;

    return NtUserCreateWindowStation( &attr, access, 0, 0, 0, 0, 0 );
140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165
}


/******************************************************************************
 *              OpenWindowStationA  (USER32.@)
 */
HWINSTA WINAPI OpenWindowStationA( LPCSTR name, BOOL inherit, ACCESS_MASK access )
{
    WCHAR buffer[MAX_PATH];

    if (!name) return OpenWindowStationW( NULL, inherit, access );

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
    return OpenWindowStationW( buffer, inherit, access );
}


/******************************************************************************
 *              OpenWindowStationW  (USER32.@)
 */
HWINSTA WINAPI OpenWindowStationW( LPCWSTR name, BOOL inherit, ACCESS_MASK access )
{
166 167 168 169 170 171 172 173 174 175 176
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING str;

    RtlInitUnicodeString( &str, name );
    if (!str.Length) RtlInitUnicodeString( &str, get_winstation_default_name() );

    InitializeObjectAttributes( &attr, &str, OBJ_CASE_INSENSITIVE,
                                get_winstations_dir_handle(), NULL );
    if (inherit) attr.Attributes |= OBJ_INHERIT;

    return NtUserOpenWindowStation( &attr, access );
177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192
}


/******************************************************************************
 *              EnumWindowStationsA  (USER32.@)
 */
BOOL WINAPI EnumWindowStationsA( WINSTAENUMPROCA func, LPARAM lparam )
{
    struct enum_proc_lparam data;
    data.func   = func;
    data.lparam = lparam;
    return EnumWindowStationsW( enum_names_WtoA, (LPARAM)&data );
}


/******************************************************************************
193
 *              EnumWindowStationsW  (USER32.@)
194 195 196
 */
BOOL WINAPI EnumWindowStationsW( WINSTAENUMPROCW func, LPARAM lparam )
{
197 198 199
    unsigned int index = 0;
    WCHAR name[MAX_PATH];
    BOOL ret = TRUE;
200
    NTSTATUS status;
201 202 203 204 205 206

    while (ret)
    {
        SERVER_START_REQ( enum_winstation )
        {
            req->index = index;
207 208 209
            wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
            status = wine_server_call( req );
            name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
210 211 212
            index = reply->next;
        }
        SERVER_END_REQ;
213 214 215 216 217 218 219 220
        if (status == STATUS_NO_MORE_ENTRIES)
            break;
        if (status)
        {
            SetLastError( RtlNtStatusToDosError( status ) );
            return FALSE;
        }
        ret = func( name, lparam );
221 222
    }
    return ret;
223 224 225 226 227 228 229 230 231 232 233 234 235 236 237 238 239 240 241 242 243 244 245 246 247 248 249 250 251 252 253 254 255
}


/***********************************************************************
 *              CreateDesktopA   (USER32.@)
 */
HDESK WINAPI CreateDesktopA( LPCSTR name, LPCSTR device, LPDEVMODEA devmode,
                             DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
{
    WCHAR buffer[MAX_PATH];

    if (device || devmode)
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return 0;
    }
    if (!name) return CreateDesktopW( NULL, NULL, NULL, flags, access, sa );

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
    return CreateDesktopW( buffer, NULL, NULL, flags, access, sa );
}


/***********************************************************************
 *              CreateDesktopW   (USER32.@)
 */
HDESK WINAPI CreateDesktopW( LPCWSTR name, LPCWSTR device, LPDEVMODEW devmode,
                             DWORD flags, ACCESS_MASK access, LPSECURITY_ATTRIBUTES sa )
{
256 257
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING str;
258

259
    if (device || (devmode && !(flags & DF_WINE_CREATE_DESKTOP)))
260 261 262 263
    {
        SetLastError( ERROR_INVALID_PARAMETER );
        return 0;
    }
264 265 266 267 268 269

    RtlInitUnicodeString( &str, name );
    InitializeObjectAttributes( &attr, &str, OBJ_CASE_INSENSITIVE | OBJ_OPENIF,
                                get_winstations_dir_handle(), NULL );
    if (sa && sa->bInheritHandle) attr.Attributes |= OBJ_INHERIT;
    return NtUserCreateDesktopEx( &attr, NULL, devmode, flags, access, 0 );
270 271 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290
}


/******************************************************************************
 *              OpenDesktopA   (USER32.@)
 */
HDESK WINAPI OpenDesktopA( LPCSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
{
    WCHAR buffer[MAX_PATH];

    if (!name) return OpenDesktopW( NULL, flags, inherit, access );

    if (!MultiByteToWideChar( CP_ACP, 0, name, -1, buffer, MAX_PATH ))
    {
        SetLastError( ERROR_FILENAME_EXCED_RANGE );
        return 0;
    }
    return OpenDesktopW( buffer, flags, inherit, access );
}


291
HDESK open_winstation_desktop( HWINSTA hwinsta, LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
292
{
293 294 295 296 297 298 299
    OBJECT_ATTRIBUTES attr;
    UNICODE_STRING str;

    RtlInitUnicodeString( &str, name );
    InitializeObjectAttributes( &attr, &str, OBJ_CASE_INSENSITIVE, hwinsta, NULL );
    if (inherit) attr.Attributes |= OBJ_INHERIT;
    return NtUserOpenDesktop( &attr, flags, access );
300 301 302
}


303 304 305 306 307 308 309 310 311
/******************************************************************************
 *              OpenDesktopW   (USER32.@)
 */
HDESK WINAPI OpenDesktopW( LPCWSTR name, DWORD flags, BOOL inherit, ACCESS_MASK access )
{
    return open_winstation_desktop( NULL, name, flags, inherit, access );
}


312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328
/******************************************************************************
 *              EnumDesktopsA   (USER32.@)
 */
BOOL WINAPI EnumDesktopsA( HWINSTA winsta, DESKTOPENUMPROCA func, LPARAM lparam )
{
    struct enum_proc_lparam data;
    data.func   = func;
    data.lparam = lparam;
    return EnumDesktopsW( winsta, enum_names_WtoA, (LPARAM)&data );
}


/******************************************************************************
 *              EnumDesktopsW   (USER32.@)
 */
BOOL WINAPI EnumDesktopsW( HWINSTA winsta, DESKTOPENUMPROCW func, LPARAM lparam )
{
329 330 331
    unsigned int index = 0;
    WCHAR name[MAX_PATH];
    BOOL ret = TRUE;
332 333 334
    NTSTATUS status;

    if (!winsta)
335
        winsta = NtUserGetProcessWindowStation();
336 337 338 339 340

    while (ret)
    {
        SERVER_START_REQ( enum_desktop )
        {
341
            req->winstation = wine_server_obj_handle( winsta );
342
            req->index      = index;
343 344 345
            wine_server_set_reply( req, name, sizeof(name) - sizeof(WCHAR) );
            status = wine_server_call( req );
            name[wine_server_reply_size(reply)/sizeof(WCHAR)] = 0;
346 347 348
            index = reply->next;
        }
        SERVER_END_REQ;
349 350 351 352 353 354 355 356
        if (status == STATUS_NO_MORE_ENTRIES)
            break;
        if (status)
        {
            SetLastError( RtlNtStatusToDosError( status ) );
            return FALSE;
        }
        ret = func(name, lparam);
357 358
    }
    return ret;
359 360 361 362 363 364 365 366 367 368 369 370
}


/***********************************************************************
 *              GetUserObjectInformationA   (USER32.@)
 */
BOOL WINAPI GetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len, LPDWORD needed )
{
    /* check for information types returning strings */
    if (index == UOI_TYPE || index == UOI_NAME)
    {
        WCHAR buffer[MAX_PATH];
371
        DWORD lenA, lenW;
372

373
        if (!NtUserGetObjectInformation( handle, index, buffer, sizeof(buffer), &lenW )) return FALSE;
374 375 376 377
        lenA = WideCharToMultiByte( CP_ACP, 0, buffer, -1, NULL, 0, NULL, NULL );
        if (needed) *needed = lenA;
        if (lenA > len)
        {
378 379 380 381
            /* If the buffer length supplied by the caller is insufficient, Windows returns a
               'needed' length based upon the Unicode byte length, so we should do similarly. */
            if (needed) *needed = lenW;

382
            SetLastError( ERROR_INSUFFICIENT_BUFFER );
383 384 385 386 387
            return FALSE;
        }
        if (info) WideCharToMultiByte( CP_ACP, 0, buffer, -1, info, len, NULL, NULL );
        return TRUE;
    }
388
    return NtUserGetObjectInformation( handle, index, info, len, needed );
389 390 391 392 393 394 395 396
}


/******************************************************************************
 *              SetUserObjectInformationA   (USER32.@)
 */
BOOL WINAPI SetUserObjectInformationA( HANDLE handle, INT index, LPVOID info, DWORD len )
{
397
    return NtUserSetObjectInformation( handle, index, info, len );
398 399 400 401 402 403 404 405 406
}


/***********************************************************************
 *              GetUserObjectSecurity   (USER32.@)
 */
BOOL WINAPI GetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
                                   PSECURITY_DESCRIPTOR sid, DWORD len, LPDWORD needed )
{
407
    FIXME( "(%p %p %p len=%ld %p),stub!\n", handle, info, sid, len, needed );
408 409 410 411 412 413 414 415
    if (needed)
        *needed = sizeof(SECURITY_DESCRIPTOR);
    if (len < sizeof(SECURITY_DESCRIPTOR))
    {
        SetLastError( ERROR_INSUFFICIENT_BUFFER );
        return FALSE;
    }
    return InitializeSecurityDescriptor(sid, SECURITY_DESCRIPTOR_REVISION);
416 417 418 419 420 421 422 423 424 425 426
}

/***********************************************************************
 *              SetUserObjectSecurity   (USER32.@)
 */
BOOL WINAPI SetUserObjectSecurity( HANDLE handle, PSECURITY_INFORMATION info,
                                   PSECURITY_DESCRIPTOR sid )
{
    FIXME( "(%p,%p,%p),stub!\n", handle, info, sid );
    return TRUE;
}