om.c 20.2 KB
Newer Older
Juergen Schmied's avatar
Juergen Schmied committed
1 2
/*
 *	Object management functions
3 4
 *
 * Copyright 1999, 2000 Juergen Schmied
5
 * Copyright 2005 Vitaliy Margolen
6 7 8 9 10 11 12 13 14 15 16 17 18
 *
 * 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
19
 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
Juergen Schmied's avatar
Juergen Schmied committed
20 21
 */

22 23
#include "config.h"

24
#include <stdarg.h>
Juergen Schmied's avatar
Juergen Schmied committed
25 26
#include <stdlib.h>
#include <string.h>
27 28 29
#ifdef HAVE_IO_H
# include <io.h>
#endif
30 31 32
#ifdef HAVE_UNISTD_H
# include <unistd.h>
#endif
Juergen Schmied's avatar
Juergen Schmied committed
33

34 35 36
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "wine/debug.h"
37
#include "windef.h"
38
#include "winternl.h"
39
#include "ntdll_misc.h"
40
#include "wine/server.h"
Juergen Schmied's avatar
Juergen Schmied committed
41

42
WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
43

Juergen Schmied's avatar
Juergen Schmied committed
44 45 46 47

/*
 *	Generic object functions
 */
48

Juergen Schmied's avatar
Juergen Schmied committed
49
/******************************************************************************
50
 * NtQueryObject [NTDLL.@]
Patrik Stridvall's avatar
Patrik Stridvall committed
51
 * ZwQueryObject [NTDLL.@]
Juergen Schmied's avatar
Juergen Schmied committed
52
 */
53 54 55
NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
                              IN OBJECT_INFORMATION_CLASS info_class,
                              OUT PVOID ptr, IN ULONG len, OUT PULONG used_len)
Juergen Schmied's avatar
Juergen Schmied committed
56
{
57 58
    NTSTATUS status;

59
    TRACE("(%p,0x%08x,%p,0x%08x,%p): stub\n",
60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106
          handle, info_class, ptr, len, used_len);

    if (used_len) *used_len = 0;

    switch (info_class)
    {
    case ObjectDataInformation:
        {
            OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;

            if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;

            SERVER_START_REQ( set_handle_info )
            {
                req->handle = handle;
                req->flags  = 0;
                req->mask   = 0;
                status = wine_server_call( req );
                if (status == STATUS_SUCCESS)
                {
                    p->InheritHandle = (reply->old_flags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
                    p->ProtectFromClose = (reply->old_flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE;
                    if (used_len) *used_len = sizeof(*p);
                }
            }
            SERVER_END_REQ;
        }
        break;
    default:
        FIXME("Unsupported information class %u\n", info_class);
        status = STATUS_NOT_IMPLEMENTED;
        break;
    }
    return status;
}

/******************************************************************
 *		NtSetInformationObject [NTDLL.@]
 *		ZwSetInformationObject [NTDLL.@]
 *
 */
NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle,
                                       IN OBJECT_INFORMATION_CLASS info_class,
                                       IN PVOID ptr, IN ULONG len)
{
    NTSTATUS status;

107
    TRACE("(%p,0x%08x,%p,0x%08x): stub\n",
108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135
          handle, info_class, ptr, len);

    switch (info_class)
    {
    case ObjectDataInformation:
        {
            OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;

            if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;

            SERVER_START_REQ( set_handle_info )
            {
                req->handle = handle;
                req->flags  = 0;
                req->mask   = HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE;
                if (p->InheritHandle)    req->flags |= HANDLE_FLAG_INHERIT;
                if (p->ProtectFromClose) req->flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
                status = wine_server_call( req );
            }
            SERVER_END_REQ;
        }
        break;
    default:
        FIXME("Unsupported information class %u\n", info_class);
        status = STATUS_NOT_IMPLEMENTED;
        break;
    }
    return status;
Juergen Schmied's avatar
Juergen Schmied committed
136 137 138
}

/******************************************************************************
139
 *  NtQuerySecurityObject	[NTDLL.@]
140
 *
Jon Griffiths's avatar
Jon Griffiths committed
141
 * An ntdll analogue to GetKernelObjectSecurity().
142 143 144
 *
 * NOTES
 *  only the lowest 4 bit of SecurityObjectInformationClass are used
145
 *  0x7-0xf returns STATUS_ACCESS_DENIED (even running with system privileges)
146
 *
Jon Griffiths's avatar
Jon Griffiths committed
147 148
 * FIXME
 *  We are constructing a fake sid (Administrators:Full, System:Full, Everyone:Read)
Juergen Schmied's avatar
Juergen Schmied committed
149
 */
150
NTSTATUS WINAPI
151 152 153 154 155 156
NtQuerySecurityObject(
	IN HANDLE Object,
	IN SECURITY_INFORMATION RequestedInformation,
	OUT PSECURITY_DESCRIPTOR pSecurityDesriptor,
	IN ULONG Length,
	OUT PULONG ResultLength)
Juergen Schmied's avatar
Juergen Schmied committed
157
{
158 159
	static const SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
	static const SID_IDENTIFIER_AUTHORITY worldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
160 161 162
	BYTE Buffer[256];
	PISECURITY_DESCRIPTOR_RELATIVE psd = (PISECURITY_DESCRIPTOR_RELATIVE)Buffer;
	UINT BufferIndex = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
163

164
	FIXME("(%p,0x%08x,%p,0x%08x,%p) stub!\n",
165 166 167 168 169 170 171 172
	Object, RequestedInformation, pSecurityDesriptor, Length, ResultLength);

	RequestedInformation &= 0x0000000f;

	if (RequestedInformation & SACL_SECURITY_INFORMATION) return STATUS_ACCESS_DENIED;

	ZeroMemory(Buffer, 256);
	RtlCreateSecurityDescriptor((PSECURITY_DESCRIPTOR)psd, SECURITY_DESCRIPTOR_REVISION);
173
	psd->Control = SE_SELF_RELATIVE |
174 175 176 177 178
	  ((RequestedInformation & DACL_SECURITY_INFORMATION) ? SE_DACL_PRESENT:0);

	/* owner: administrator S-1-5-20-220*/
	if (OWNER_SECURITY_INFORMATION & RequestedInformation)
	{
179
	  SID* psid = (SID*)&(Buffer[BufferIndex]);
180 181 182 183 184 185 186 187 188 189

	  psd->Owner = BufferIndex;
	  BufferIndex += RtlLengthRequiredSid(2);

	  psid->Revision = SID_REVISION;
	  psid->SubAuthorityCount = 2;
	  psid->IdentifierAuthority = localSidAuthority;
	  psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
	  psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS;
	}
190

191 192 193
	/* group: built in domain S-1-5-12 */
	if (GROUP_SECURITY_INFORMATION & RequestedInformation)
	{
194
	  SID* psid = (SID*) &(Buffer[BufferIndex]);
195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210

	  psd->Group = BufferIndex;
	  BufferIndex += RtlLengthRequiredSid(1);

	  psid->Revision = SID_REVISION;
	  psid->SubAuthorityCount = 1;
	  psid->IdentifierAuthority = localSidAuthority;
	  psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
	}

	/* discretionary ACL */
	if (DACL_SECURITY_INFORMATION & RequestedInformation)
	{
	  /* acl header */
	  PACL pacl = (PACL)&(Buffer[BufferIndex]);
	  PACCESS_ALLOWED_ACE pace;
211
	  SID* psid;
212

213 214 215 216 217 218 219
	  psd->Dacl = BufferIndex;

	  pacl->AclRevision = MIN_ACL_REVISION;
	  pacl->AceCount = 3;
	  pacl->AclSize = BufferIndex; /* storing the start index temporary */

	  BufferIndex += sizeof(ACL);
220

221 222 223 224 225 226 227 228 229 230 231
	  /* ACE System - full access */
	  pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]);
	  BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);

	  pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
	  pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
	  pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1);
	  pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f;
	  pace->SidStart = BufferIndex;

	  /* SID S-1-5-12 (System) */
232
	  psid = (SID*)&(Buffer[BufferIndex]);
233 234 235 236 237 238 239

	  BufferIndex += RtlLengthRequiredSid(1);

	  psid->Revision = SID_REVISION;
	  psid->SubAuthorityCount = 1;
	  psid->IdentifierAuthority = localSidAuthority;
	  psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
240

241 242 243 244 245 246 247 248 249 250 251
	  /* ACE Administrators - full access*/
	  pace = (PACCESS_ALLOWED_ACE) &(Buffer[BufferIndex]);
	  BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);

	  pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
	  pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
	  pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(2);
	  pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f;
	  pace->SidStart = BufferIndex;

	  /* S-1-5-12 (Administrators) */
252
	  psid = (SID*)&(Buffer[BufferIndex]);
253 254 255 256 257 258 259 260

	  BufferIndex += RtlLengthRequiredSid(2);

	  psid->Revision = SID_REVISION;
	  psid->SubAuthorityCount = 2;
	  psid->IdentifierAuthority = localSidAuthority;
	  psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
	  psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS;
261

262 263 264 265 266 267 268 269 270 271 272
	  /* ACE Everyone - read access */
	  pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]);
	  BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);

	  pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
	  pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
	  pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1);
	  pace->Mask = READ_CONTROL| 0x19;
	  pace->SidStart = BufferIndex;

	  /* SID S-1-1-0 (Everyone) */
273
	  psid = (SID*)&(Buffer[BufferIndex]);
274 275 276 277 278 279 280 281 282 283 284 285

	  BufferIndex += RtlLengthRequiredSid(1);

	  psid->Revision = SID_REVISION;
	  psid->SubAuthorityCount = 1;
	  psid->IdentifierAuthority = worldSidAuthority;
	  psid->SubAuthority[0] = 0;

	  /* calculate used bytes */
	  pacl->AclSize = BufferIndex - pacl->AclSize;
	}
	*ResultLength = BufferIndex;
286
	TRACE("len=%u\n", *ResultLength);
287 288 289 290
	if (Length < *ResultLength) return STATUS_BUFFER_TOO_SMALL;
	memcpy(pSecurityDesriptor, Buffer, *ResultLength);

	return STATUS_SUCCESS;
Juergen Schmied's avatar
Juergen Schmied committed
291
}
292 293


Juergen Schmied's avatar
Juergen Schmied committed
294
/******************************************************************************
295
 *  NtDuplicateObject		[NTDLL.@]
Patrik Stridvall's avatar
Patrik Stridvall committed
296
 *  ZwDuplicateObject		[NTDLL.@]
Juergen Schmied's avatar
Juergen Schmied committed
297
 */
298 299 300
NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
                                   HANDLE dest_process, PHANDLE dest,
                                   ACCESS_MASK access, ULONG attributes, ULONG options )
Juergen Schmied's avatar
Juergen Schmied committed
301
{
302 303 304 305 306 307 308
    NTSTATUS ret;
    SERVER_START_REQ( dup_handle )
    {
        req->src_process = source_process;
        req->src_handle  = source;
        req->dst_process = dest_process;
        req->access      = access;
309
        req->attributes  = attributes;
310 311 312 313 314
        req->options     = options;

        if (!(ret = wine_server_call( req )))
        {
            if (dest) *dest = reply->handle;
315 316 317 318
            if (reply->closed)
                server_remove_fd_from_cache( source );
            else if (options & DUPLICATE_CLOSE_SOURCE)
                WARN( "failed to close handle %p in process %p\n", source, source_process );
319 320 321 322
        }
    }
    SERVER_END_REQ;
    return ret;
Juergen Schmied's avatar
Juergen Schmied committed
323 324 325
}

/**************************************************************************
326
 *                 NtClose				[NTDLL.@]
Jon Griffiths's avatar
Jon Griffiths committed
327 328 329 330 331 332 333 334 335
 *
 * Close a handle reference to an object.
 * 
 * PARAMS
 *  Handle [I] handle to close
 *
 * RETURNS
 *  Success: ERROR_SUCCESS.
 *  Failure: An NTSTATUS error code.
Juergen Schmied's avatar
Juergen Schmied committed
336
 */
337
NTSTATUS WINAPI NtClose( HANDLE Handle )
Juergen Schmied's avatar
Juergen Schmied committed
338
{
339
    NTSTATUS ret;
340
    SERVER_START_REQ( close_handle )
341 342
    {
        req->handle = Handle;
343
        ret = wine_server_call( req );
344
        if (!ret) server_remove_fd_from_cache( Handle );
345 346 347
    }
    SERVER_END_REQ;
    return ret;
Juergen Schmied's avatar
Juergen Schmied committed
348 349 350 351 352 353 354
}

/*
 *	Directory functions
 */

/**************************************************************************
355
 * NtOpenDirectoryObject [NTDLL.@]
Patrik Stridvall's avatar
Patrik Stridvall committed
356
 * ZwOpenDirectoryObject [NTDLL.@]
Jon Griffiths's avatar
Jon Griffiths committed
357 358 359 360 361 362 363 364 365 366 367
 *
 * Open a namespace directory object.
 * 
 * PARAMS
 *  DirectoryHandle  [O] Destination for the new directory handle
 *  DesiredAccess    [I] Desired access to the directory
 *  ObjectAttributes [I] Structure describing the directory
 *
 * RETURNS
 *  Success: ERROR_SUCCESS.
 *  Failure: An NTSTATUS error code.
Juergen Schmied's avatar
Juergen Schmied committed
368
 */
369 370
NTSTATUS WINAPI NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
                                      POBJECT_ATTRIBUTES ObjectAttributes)
Juergen Schmied's avatar
Juergen Schmied committed
371
{
372
    NTSTATUS ret;
373
    TRACE("(%p,0x%08x)\n", DirectoryHandle, DesiredAccess);
374 375 376 377 378 379 380 381 382 383 384 385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400
    dump_ObjectAttributes(ObjectAttributes);

    if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
    if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
    /* Have to test it here because server won't know difference between
     * ObjectName == NULL and ObjectName == "" */
    if (!ObjectAttributes->ObjectName)
    {
        if (ObjectAttributes->RootDirectory)
            return STATUS_OBJECT_NAME_INVALID;
        else
            return STATUS_OBJECT_PATH_SYNTAX_BAD;
    }

    SERVER_START_REQ(open_directory)
    {
        req->access = DesiredAccess;
        req->attributes = ObjectAttributes->Attributes;
        req->rootdir = ObjectAttributes->RootDirectory;
        if (ObjectAttributes->ObjectName)
            wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
                                 ObjectAttributes->ObjectName->Length);
        ret = wine_server_call( req );
        *DirectoryHandle = reply->handle;
    }
    SERVER_END_REQ;
    return ret;
Juergen Schmied's avatar
Juergen Schmied committed
401 402 403
}

/******************************************************************************
404
 *  NtCreateDirectoryObject	[NTDLL.@]
Patrik Stridvall's avatar
Patrik Stridvall committed
405
 *  ZwCreateDirectoryObject	[NTDLL.@]
406 407 408 409 410 411 412 413 414 415 416
 *
 * Create a namespace directory object.
 * 
 * PARAMS
 *  DirectoryHandle  [O] Destination for the new directory handle
 *  DesiredAccess    [I] Desired access to the directory
 *  ObjectAttributes [I] Structure describing the directory
 *
 * RETURNS
 *  Success: ERROR_SUCCESS.
 *  Failure: An NTSTATUS error code.
Juergen Schmied's avatar
Juergen Schmied committed
417
 */
418 419
NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
                                        POBJECT_ATTRIBUTES ObjectAttributes)
Juergen Schmied's avatar
Juergen Schmied committed
420
{
421
    NTSTATUS ret;
422
    TRACE("(%p,0x%08x)\n", DirectoryHandle, DesiredAccess);
423 424 425 426 427 428 429 430 431 432 433 434 435 436 437 438 439
    dump_ObjectAttributes(ObjectAttributes);

    if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;

    SERVER_START_REQ(create_directory)
    {
        req->access = DesiredAccess;
        req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
        req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
        if (ObjectAttributes && ObjectAttributes->ObjectName)
            wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
                                 ObjectAttributes->ObjectName->Length);
        ret = wine_server_call( req );
        *DirectoryHandle = reply->handle;
    }
    SERVER_END_REQ;
    return ret;
Juergen Schmied's avatar
Juergen Schmied committed
440 441 442
}

/******************************************************************************
443
 * NtQueryDirectoryObject [NTDLL.@]
Patrik Stridvall's avatar
Patrik Stridvall committed
444
 * ZwQueryDirectoryObject [NTDLL.@]
Jon Griffiths's avatar
Jon Griffiths committed
445 446 447 448
 *
 * Read information from a namespace directory.
 * 
 * PARAMS
449 450
 *  DirectoryHandle   [I]   Handle to a directory object
 *  Buffer            [O]   Buffer to hold the read data
Jon Griffiths's avatar
Jon Griffiths committed
451
 *  BufferLength      [I]   Size of the buffer in bytes
452 453 454 455
 *  ReturnSingleEntry [I]   If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
 *  RestartScan       [I]   If TRUE, start scanning from the start, if FALSE, scan from Context
 *  Context           [I/O] Indicates what point of the directory the scan is at
 *  ReturnLength      [O]   Caller supplied storage for the number of bytes written (or NULL)
Jon Griffiths's avatar
Jon Griffiths committed
456 457 458 459
 *
 * RETURNS
 *  Success: ERROR_SUCCESS.
 *  Failure: An NTSTATUS error code.
Juergen Schmied's avatar
Juergen Schmied committed
460
 */
461 462 463
NTSTATUS WINAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PDIRECTORY_BASIC_INFORMATION Buffer,
                                       IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan,
                                       IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
Juergen Schmied's avatar
Juergen Schmied committed
464
{
465
    FIXME("(%p,%p,0x%08x,0x%08x,0x%08x,%p,%p), stub\n", DirectoryHandle, Buffer, BufferLength, ReturnSingleEntry,
466 467 468
          RestartScan, Context, ReturnLength);

    return STATUS_NOT_IMPLEMENTED;
Juergen Schmied's avatar
Juergen Schmied committed
469 470 471 472 473
}

/*
 *	Link objects
 */
474

Juergen Schmied's avatar
Juergen Schmied committed
475
/******************************************************************************
476
 *  NtOpenSymbolicLinkObject	[NTDLL.@]
477 478 479 480 481 482 483 484 485 486 487 488
 *  ZwOpenSymbolicLinkObject	[NTDLL.@]
 *
 * Open a namespace symbolic link object.
 * 
 * PARAMS
 *  LinkHandle       [O] Destination for the new symbolic link handle
 *  DesiredAccess    [I] Desired access to the symbolic link
 *  ObjectAttributes [I] Structure describing the symbolic link
 *
 * RETURNS
 *  Success: ERROR_SUCCESS.
 *  Failure: An NTSTATUS error code.
Juergen Schmied's avatar
Juergen Schmied committed
489
 */
490 491
NTSTATUS WINAPI NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle, IN ACCESS_MASK DesiredAccess,
                                         IN POBJECT_ATTRIBUTES ObjectAttributes)
Juergen Schmied's avatar
Juergen Schmied committed
492
{
493
    NTSTATUS ret;
494
    TRACE("(%p,0x%08x,%p)\n",LinkHandle, DesiredAccess, ObjectAttributes);
495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511
    dump_ObjectAttributes(ObjectAttributes);

    if (!LinkHandle) return STATUS_ACCESS_VIOLATION;
    if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
    /* Have to test it here because server won't know difference between
     * ObjectName == NULL and ObjectName == "" */
    if (!ObjectAttributes->ObjectName)
    {
        if (ObjectAttributes->RootDirectory)
            return STATUS_OBJECT_NAME_INVALID;
        else
            return STATUS_OBJECT_PATH_SYNTAX_BAD;
    }

    SERVER_START_REQ(open_symlink)
    {
        req->access = DesiredAccess;
512 513
        req->attributes = ObjectAttributes->Attributes;
        req->rootdir = ObjectAttributes->RootDirectory;
514 515 516 517 518 519 520 521
        if (ObjectAttributes->ObjectName)
            wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
                                 ObjectAttributes->ObjectName->Length);
        ret = wine_server_call( req );
        *LinkHandle = reply->handle;
    }
    SERVER_END_REQ;
    return ret;
Juergen Schmied's avatar
Juergen Schmied committed
522 523 524
}

/******************************************************************************
525
 *  NtCreateSymbolicLinkObject	[NTDLL.@]
526 527 528 529 530 531 532 533 534 535 536 537 538
 *  ZwCreateSymbolicLinkObject	[NTDLL.@]
 *
 * Open a namespace symbolic link object.
 * 
 * PARAMS
 *  SymbolicLinkHandle [O] Destination for the new symbolic link handle
 *  DesiredAccess      [I] Desired access to the symbolic link
 *  ObjectAttributes   [I] Structure describing the symbolic link
 *  TargetName         [I] Name of the target symbolic link points to
 *
 * RETURNS
 *  Success: ERROR_SUCCESS.
 *  Failure: An NTSTATUS error code.
Juergen Schmied's avatar
Juergen Schmied committed
539
 */
540 541 542
NTSTATUS WINAPI NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,IN ACCESS_MASK DesiredAccess,
	                                   IN POBJECT_ATTRIBUTES ObjectAttributes,
                                           IN PUNICODE_STRING TargetName)
Juergen Schmied's avatar
Juergen Schmied committed
543
{
544
    NTSTATUS ret;
545
    TRACE("(%p,0x%08x,%p, -> %s)\n", SymbolicLinkHandle, DesiredAccess, ObjectAttributes,
546 547 548 549 550 551 552 553 554 555 556 557 558 559 560 561 562 563 564 565 566 567 568 569 570
                                      debugstr_us(TargetName));
    dump_ObjectAttributes(ObjectAttributes);

    if (!SymbolicLinkHandle || !TargetName) return STATUS_ACCESS_VIOLATION;
    if (!TargetName->Buffer) return STATUS_INVALID_PARAMETER;

    SERVER_START_REQ(create_symlink)
    {
        req->access = DesiredAccess;
        req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
        req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
        if (ObjectAttributes->ObjectName)
        {
            req->name_len = ObjectAttributes->ObjectName->Length;
            wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
                                 ObjectAttributes->ObjectName->Length);
        }
        else
            req->name_len = 0;
        wine_server_add_data(req, TargetName->Buffer, TargetName->Length);
        ret = wine_server_call( req );
        *SymbolicLinkHandle = reply->handle;
    }
    SERVER_END_REQ;
    return ret;
Juergen Schmied's avatar
Juergen Schmied committed
571 572 573
}

/******************************************************************************
574
 *  NtQuerySymbolicLinkObject	[NTDLL.@]
575 576 577 578 579 580 581 582 583 584 585 586
 *  ZwQuerySymbolicLinkObject	[NTDLL.@]
 *
 * Query a namespace symbolic link object target name.
 * 
 * PARAMS
 *  LinkHandle     [I] Handle to a symbolic link object
 *  LinkTarget     [O] Destination for the symbolic link target
 *  ReturnedLength [O] Size of returned data
 *
 * RETURNS
 *  Success: ERROR_SUCCESS.
 *  Failure: An NTSTATUS error code.
Juergen Schmied's avatar
Juergen Schmied committed
587
 */
588 589
NTSTATUS WINAPI NtQuerySymbolicLinkObject(IN HANDLE LinkHandle, IN OUT PUNICODE_STRING LinkTarget,
                                          OUT PULONG ReturnedLength OPTIONAL)
Juergen Schmied's avatar
Juergen Schmied committed
590
{
591 592
    NTSTATUS ret;
    TRACE("(%p,%p,%p)\n", LinkHandle, LinkTarget, ReturnedLength);
Juergen Schmied's avatar
Juergen Schmied committed
593

594 595 596 597 598 599 600 601 602 603 604 605 606 607
    if (!LinkTarget) return STATUS_ACCESS_VIOLATION;

    SERVER_START_REQ(query_symlink)
    {
        req->handle = LinkHandle;
        wine_server_set_reply( req, LinkTarget->Buffer, LinkTarget->MaximumLength );
        if (!(ret = wine_server_call( req )))
        {
            LinkTarget->Length = wine_server_reply_size(reply);
            if (ReturnedLength) *ReturnedLength = LinkTarget->Length;
        }
    }
    SERVER_END_REQ;
    return ret;
Juergen Schmied's avatar
Juergen Schmied committed
608 609
}

Andreas Mohr's avatar
Andreas Mohr committed
610
/******************************************************************************
611
 *  NtAllocateUuids   [NTDLL.@]
Andreas Mohr's avatar
Andreas Mohr committed
612
 */
613 614 615 616
NTSTATUS WINAPI NtAllocateUuids(
        PULARGE_INTEGER Time,
        PULONG Range,
        PULONG Sequence)
Andreas Mohr's avatar
Andreas Mohr committed
617
{
618
        FIXME("(%p,%p,%p), stub.\n", Time, Range, Sequence);
Andreas Mohr's avatar
Andreas Mohr committed
619 620
	return 0;
}