Added CSIDL_MYVIDEO|MYPICTURES|MYMUSIC to _SHRegisterUserShellFolders.
[wine] / dlls / ntdll / om.c
1 /*
2  *      Object management functions
3  *
4  * Copyright 1999, 2000 Juergen Schmied
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 "config.h"
22
23 #include <stdarg.h>
24 #include <stdlib.h>
25 #include <string.h>
26 #ifdef HAVE_IO_H
27 # include <io.h>
28 #endif
29 #ifdef HAVE_UNISTD_H
30 # include <unistd.h>
31 #endif
32
33 #include "ntstatus.h"
34 #define WIN32_NO_STATUS
35 #include "wine/debug.h"
36 #include "windef.h"
37 #include "winternl.h"
38 #include "ntdll_misc.h"
39 #include "wine/server.h"
40
41 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
42
43
44 /*
45  *      Generic object functions
46  */
47
48 /******************************************************************************
49  * NtQueryObject [NTDLL.@]
50  * ZwQueryObject [NTDLL.@]
51  */
52 NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
53                               IN OBJECT_INFORMATION_CLASS info_class,
54                               OUT PVOID ptr, IN ULONG len, OUT PULONG used_len)
55 {
56     NTSTATUS status;
57
58     TRACE("(%p,0x%08x,%p,0x%08lx,%p): stub\n",
59           handle, info_class, ptr, len, used_len);
60
61     if (used_len) *used_len = 0;
62
63     switch (info_class)
64     {
65     case ObjectDataInformation:
66         {
67             OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;
68
69             if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
70
71             SERVER_START_REQ( set_handle_info )
72             {
73                 req->handle = handle;
74                 req->flags  = 0;
75                 req->mask   = 0;
76                 status = wine_server_call( req );
77                 if (status == STATUS_SUCCESS)
78                 {
79                     p->InheritHandle = (reply->old_flags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
80                     p->ProtectFromClose = (reply->old_flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE;
81                     if (used_len) *used_len = sizeof(*p);
82                 }
83             }
84             SERVER_END_REQ;
85         }
86         break;
87     default:
88         FIXME("Unsupported information class %u\n", info_class);
89         status = STATUS_NOT_IMPLEMENTED;
90         break;
91     }
92     return status;
93 }
94
95 /******************************************************************
96  *              NtSetInformationObject [NTDLL.@]
97  *              ZwSetInformationObject [NTDLL.@]
98  *
99  */
100 NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle,
101                                        IN OBJECT_INFORMATION_CLASS info_class,
102                                        IN PVOID ptr, IN ULONG len)
103 {
104     NTSTATUS status;
105
106     TRACE("(%p,0x%08x,%p,0x%08lx): stub\n",
107           handle, info_class, ptr, len);
108
109     switch (info_class)
110     {
111     case ObjectDataInformation:
112         {
113             OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;
114
115             if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
116
117             SERVER_START_REQ( set_handle_info )
118             {
119                 req->handle = handle;
120                 req->flags  = 0;
121                 req->mask   = HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE;
122                 if (p->InheritHandle)    req->flags |= HANDLE_FLAG_INHERIT;
123                 if (p->ProtectFromClose) req->flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
124                 status = wine_server_call( req );
125             }
126             SERVER_END_REQ;
127         }
128         break;
129     default:
130         FIXME("Unsupported information class %u\n", info_class);
131         status = STATUS_NOT_IMPLEMENTED;
132         break;
133     }
134     return status;
135 }
136
137 /******************************************************************************
138  *  NtQuerySecurityObject       [NTDLL.@]
139  *
140  * An ntdll analogue to GetKernelObjectSecurity().
141  *
142  * NOTES
143  *  only the lowest 4 bit of SecurityObjectInformationClass are used
144  *  0x7-0xf returns STATUS_ACCESS_DENIED (even running with system privileges)
145  *
146  * FIXME
147  *  We are constructing a fake sid (Administrators:Full, System:Full, Everyone:Read)
148  */
149 NTSTATUS WINAPI
150 NtQuerySecurityObject(
151         IN HANDLE Object,
152         IN SECURITY_INFORMATION RequestedInformation,
153         OUT PSECURITY_DESCRIPTOR pSecurityDesriptor,
154         IN ULONG Length,
155         OUT PULONG ResultLength)
156 {
157         static SID_IDENTIFIER_AUTHORITY localSidAuthority = {SECURITY_NT_AUTHORITY};
158         static SID_IDENTIFIER_AUTHORITY worldSidAuthority = {SECURITY_WORLD_SID_AUTHORITY};
159         BYTE Buffer[256];
160         PISECURITY_DESCRIPTOR_RELATIVE psd = (PISECURITY_DESCRIPTOR_RELATIVE)Buffer;
161         UINT BufferIndex = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
162
163         FIXME("(%p,0x%08lx,%p,0x%08lx,%p) stub!\n",
164         Object, RequestedInformation, pSecurityDesriptor, Length, ResultLength);
165
166         RequestedInformation &= 0x0000000f;
167
168         if (RequestedInformation & SACL_SECURITY_INFORMATION) return STATUS_ACCESS_DENIED;
169
170         ZeroMemory(Buffer, 256);
171         RtlCreateSecurityDescriptor((PSECURITY_DESCRIPTOR)psd, SECURITY_DESCRIPTOR_REVISION);
172         psd->Control = SE_SELF_RELATIVE |
173           ((RequestedInformation & DACL_SECURITY_INFORMATION) ? SE_DACL_PRESENT:0);
174
175         /* owner: administrator S-1-5-20-220*/
176         if (OWNER_SECURITY_INFORMATION & RequestedInformation)
177         {
178           SID* psid = (SID*)&(Buffer[BufferIndex]);
179
180           psd->Owner = BufferIndex;
181           BufferIndex += RtlLengthRequiredSid(2);
182
183           psid->Revision = SID_REVISION;
184           psid->SubAuthorityCount = 2;
185           psid->IdentifierAuthority = localSidAuthority;
186           psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
187           psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS;
188         }
189
190         /* group: built in domain S-1-5-12 */
191         if (GROUP_SECURITY_INFORMATION & RequestedInformation)
192         {
193           SID* psid = (SID*) &(Buffer[BufferIndex]);
194
195           psd->Group = BufferIndex;
196           BufferIndex += RtlLengthRequiredSid(1);
197
198           psid->Revision = SID_REVISION;
199           psid->SubAuthorityCount = 1;
200           psid->IdentifierAuthority = localSidAuthority;
201           psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
202         }
203
204         /* discretionary ACL */
205         if (DACL_SECURITY_INFORMATION & RequestedInformation)
206         {
207           /* acl header */
208           PACL pacl = (PACL)&(Buffer[BufferIndex]);
209           PACCESS_ALLOWED_ACE pace;
210           SID* psid;
211
212           psd->Dacl = BufferIndex;
213
214           pacl->AclRevision = MIN_ACL_REVISION;
215           pacl->AceCount = 3;
216           pacl->AclSize = BufferIndex; /* storing the start index temporary */
217
218           BufferIndex += sizeof(ACL);
219
220           /* ACE System - full access */
221           pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]);
222           BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);
223
224           pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
225           pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
226           pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1);
227           pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f;
228           pace->SidStart = BufferIndex;
229
230           /* SID S-1-5-12 (System) */
231           psid = (SID*)&(Buffer[BufferIndex]);
232
233           BufferIndex += RtlLengthRequiredSid(1);
234
235           psid->Revision = SID_REVISION;
236           psid->SubAuthorityCount = 1;
237           psid->IdentifierAuthority = localSidAuthority;
238           psid->SubAuthority[0] = SECURITY_LOCAL_SYSTEM_RID;
239
240           /* ACE Administrators - full access*/
241           pace = (PACCESS_ALLOWED_ACE) &(Buffer[BufferIndex]);
242           BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);
243
244           pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
245           pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
246           pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(2);
247           pace->Mask = DELETE | READ_CONTROL | WRITE_DAC | WRITE_OWNER  | 0x3f;
248           pace->SidStart = BufferIndex;
249
250           /* S-1-5-12 (Administrators) */
251           psid = (SID*)&(Buffer[BufferIndex]);
252
253           BufferIndex += RtlLengthRequiredSid(2);
254
255           psid->Revision = SID_REVISION;
256           psid->SubAuthorityCount = 2;
257           psid->IdentifierAuthority = localSidAuthority;
258           psid->SubAuthority[0] = SECURITY_BUILTIN_DOMAIN_RID;
259           psid->SubAuthority[1] = DOMAIN_ALIAS_RID_ADMINS;
260
261           /* ACE Everyone - read access */
262           pace = (PACCESS_ALLOWED_ACE)&(Buffer[BufferIndex]);
263           BufferIndex += sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD);
264
265           pace->Header.AceType = ACCESS_ALLOWED_ACE_TYPE;
266           pace->Header.AceFlags = CONTAINER_INHERIT_ACE;
267           pace->Header.AceSize = sizeof(ACCESS_ALLOWED_ACE)-sizeof(DWORD) + RtlLengthRequiredSid(1);
268           pace->Mask = READ_CONTROL| 0x19;
269           pace->SidStart = BufferIndex;
270
271           /* SID S-1-1-0 (Everyone) */
272           psid = (SID*)&(Buffer[BufferIndex]);
273
274           BufferIndex += RtlLengthRequiredSid(1);
275
276           psid->Revision = SID_REVISION;
277           psid->SubAuthorityCount = 1;
278           psid->IdentifierAuthority = worldSidAuthority;
279           psid->SubAuthority[0] = 0;
280
281           /* calculate used bytes */
282           pacl->AclSize = BufferIndex - pacl->AclSize;
283         }
284         *ResultLength = BufferIndex;
285         TRACE("len=%lu\n", *ResultLength);
286         if (Length < *ResultLength) return STATUS_BUFFER_TOO_SMALL;
287         memcpy(pSecurityDesriptor, Buffer, *ResultLength);
288
289         return STATUS_SUCCESS;
290 }
291
292
293 /******************************************************************************
294  *  NtDuplicateObject           [NTDLL.@]
295  *  ZwDuplicateObject           [NTDLL.@]
296  */
297 NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
298                                    HANDLE dest_process, PHANDLE dest,
299                                    ACCESS_MASK access, ULONG attributes, ULONG options )
300 {
301     NTSTATUS ret;
302     SERVER_START_REQ( dup_handle )
303     {
304         req->src_process = source_process;
305         req->src_handle  = source;
306         req->dst_process = dest_process;
307         req->access      = access;
308         req->inherit     = (attributes & OBJ_INHERIT) != 0;
309         req->options     = options;
310
311         if (!(ret = wine_server_call( req )))
312         {
313             if (dest) *dest = reply->handle;
314             if (reply->fd != -1) close( reply->fd );
315         }
316     }
317     SERVER_END_REQ;
318     return ret;
319 }
320
321 /**************************************************************************
322  *                 NtClose                              [NTDLL.@]
323  *
324  * Close a handle reference to an object.
325  * 
326  * PARAMS
327  *  Handle [I] handle to close
328  *
329  * RETURNS
330  *  Success: ERROR_SUCCESS.
331  *  Failure: An NTSTATUS error code.
332  */
333 NTSTATUS WINAPI NtClose( HANDLE Handle )
334 {
335     NTSTATUS ret;
336     SERVER_START_REQ( close_handle )
337     {
338         req->handle = Handle;
339         ret = wine_server_call( req );
340         if (!ret && reply->fd != -1) close( reply->fd );
341     }
342     SERVER_END_REQ;
343     return ret;
344 }
345
346 /*
347  *      Directory functions
348  */
349
350 /**************************************************************************
351  * NtOpenDirectoryObject [NTDLL.@]
352  * ZwOpenDirectoryObject [NTDLL.@]
353  *
354  * Open a namespace directory object.
355  * 
356  * PARAMS
357  *  DirectoryHandle  [O] Destination for the new directory handle
358  *  DesiredAccess    [I] Desired access to the directory
359  *  ObjectAttributes [I] Structure describing the directory
360  *
361  * RETURNS
362  *  Success: ERROR_SUCCESS.
363  *  Failure: An NTSTATUS error code.
364  */
365 NTSTATUS WINAPI NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
366                                       POBJECT_ATTRIBUTES ObjectAttributes)
367 {
368     NTSTATUS ret;
369     TRACE("(%p,0x%08lx)\n", DirectoryHandle, DesiredAccess);
370     dump_ObjectAttributes(ObjectAttributes);
371
372     if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
373     if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
374     /* Have to test it here because server won't know difference between
375      * ObjectName == NULL and ObjectName == "" */
376     if (!ObjectAttributes->ObjectName)
377     {
378         if (ObjectAttributes->RootDirectory)
379             return STATUS_OBJECT_NAME_INVALID;
380         else
381             return STATUS_OBJECT_PATH_SYNTAX_BAD;
382     }
383
384     SERVER_START_REQ(open_directory)
385     {
386         req->access = DesiredAccess;
387         req->attributes = ObjectAttributes->Attributes;
388         req->rootdir = ObjectAttributes->RootDirectory;
389         if (ObjectAttributes->ObjectName)
390             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
391                                  ObjectAttributes->ObjectName->Length);
392         ret = wine_server_call( req );
393         *DirectoryHandle = reply->handle;
394     }
395     SERVER_END_REQ;
396     return ret;
397 }
398
399 /******************************************************************************
400  *  NtCreateDirectoryObject     [NTDLL.@]
401  *  ZwCreateDirectoryObject     [NTDLL.@]
402  *
403  * Create a namespace directory object.
404  * 
405  * PARAMS
406  *  DirectoryHandle  [O] Destination for the new directory handle
407  *  DesiredAccess    [I] Desired access to the directory
408  *  ObjectAttributes [I] Structure describing the directory
409  *
410  * RETURNS
411  *  Success: ERROR_SUCCESS.
412  *  Failure: An NTSTATUS error code.
413  */
414 NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
415                                         POBJECT_ATTRIBUTES ObjectAttributes)
416 {
417     NTSTATUS ret;
418     TRACE("(%p,0x%08lx)\n", DirectoryHandle, DesiredAccess);
419     dump_ObjectAttributes(ObjectAttributes);
420
421     if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
422
423     SERVER_START_REQ(create_directory)
424     {
425         req->access = DesiredAccess;
426         req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
427         req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
428         if (ObjectAttributes && ObjectAttributes->ObjectName)
429             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
430                                  ObjectAttributes->ObjectName->Length);
431         ret = wine_server_call( req );
432         *DirectoryHandle = reply->handle;
433     }
434     SERVER_END_REQ;
435     return ret;
436 }
437
438 /******************************************************************************
439  * NtQueryDirectoryObject [NTDLL.@]
440  * ZwQueryDirectoryObject [NTDLL.@]
441  *
442  * Read information from a namespace directory.
443  * 
444  * PARAMS
445  *  DirectoryHandle   [I]   Handle to a directory object
446  *  Buffer            [O]   Buffer to hold the read data
447  *  BufferLength      [I]   Size of the buffer in bytes
448  *  ReturnSingleEntry [I]   If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
449  *  RestartScan       [I]   If TRUE, start scanning from the start, if FALSE, scan from Context
450  *  Context           [I/O] Indicates what point of the directory the scan is at
451  *  ReturnLength      [O]   Caller supplied storage for the number of bytes written (or NULL)
452  *
453  * RETURNS
454  *  Success: ERROR_SUCCESS.
455  *  Failure: An NTSTATUS error code.
456  */
457 NTSTATUS WINAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PDIRECTORY_BASIC_INFORMATION Buffer,
458                                        IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan,
459                                        IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
460 {
461     FIXME("(%p,%p,0x%08lx,0x%08x,0x%08x,%p,%p), stub\n", DirectoryHandle, Buffer, BufferLength, ReturnSingleEntry,
462           RestartScan, Context, ReturnLength);
463
464     return STATUS_NOT_IMPLEMENTED;
465 }
466
467 /*
468  *      Link objects
469  */
470
471 /******************************************************************************
472  *  NtOpenSymbolicLinkObject    [NTDLL.@]
473  */
474 NTSTATUS WINAPI NtOpenSymbolicLinkObject(
475         OUT PHANDLE LinkHandle,
476         IN ACCESS_MASK DesiredAccess,
477         IN POBJECT_ATTRIBUTES ObjectAttributes)
478 {
479         FIXME("(%p,0x%08lx,%p) stub\n",
480         LinkHandle, DesiredAccess, ObjectAttributes);
481         dump_ObjectAttributes(ObjectAttributes);
482         return STATUS_OBJECT_NAME_NOT_FOUND;
483 }
484
485 /******************************************************************************
486  *  NtCreateSymbolicLinkObject  [NTDLL.@]
487  */
488 NTSTATUS WINAPI NtCreateSymbolicLinkObject(
489         OUT PHANDLE SymbolicLinkHandle,
490         IN ACCESS_MASK DesiredAccess,
491         IN POBJECT_ATTRIBUTES ObjectAttributes,
492         IN PUNICODE_STRING Name)
493 {
494         FIXME("(%p,0x%08lx,%p, %p) stub\n",
495         SymbolicLinkHandle, DesiredAccess, ObjectAttributes, debugstr_us(Name));
496         dump_ObjectAttributes(ObjectAttributes);
497         return 0;
498 }
499
500 /******************************************************************************
501  *  NtQuerySymbolicLinkObject   [NTDLL.@]
502  */
503 NTSTATUS WINAPI NtQuerySymbolicLinkObject(
504         IN HANDLE LinkHandle,
505         IN OUT PUNICODE_STRING LinkTarget,
506         OUT PULONG ReturnedLength OPTIONAL)
507 {
508         FIXME("(%p,%p,%p) stub\n",
509         LinkHandle, debugstr_us(LinkTarget), ReturnedLength);
510
511         return 0;
512 }
513
514 /******************************************************************************
515  *  NtAllocateUuids   [NTDLL.@]
516  */
517 NTSTATUS WINAPI NtAllocateUuids(
518         PULARGE_INTEGER Time,
519         PULONG Range,
520         PULONG Sequence)
521 {
522         FIXME("(%p,%p,%p), stub.\n", Time, Range, Sequence);
523         return 0;
524 }