d3dx8: Implement D3DXMatrixfDeterminant.
[wine] / dlls / ntdll / om.c
1 /*
2  *      Object management functions
3  *
4  * Copyright 1999, 2000 Juergen Schmied
5  * Copyright 2005 Vitaliy Margolen
6  *
7  * This library is free software; you can redistribute it and/or
8  * modify it under the terms of the GNU Lesser General Public
9  * License as published by the Free Software Foundation; either
10  * version 2.1 of the License, or (at your option) any later version.
11  *
12  * This library is distributed in the hope that it will be useful,
13  * but WITHOUT ANY WARRANTY; without even the implied warranty of
14  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
15  * Lesser General Public License for more details.
16  *
17  * You should have received a copy of the GNU Lesser General Public
18  * 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
20  */
21
22 #include "config.h"
23
24 #include <stdarg.h>
25 #include <stdlib.h>
26 #include <string.h>
27 #ifdef HAVE_IO_H
28 # include <io.h>
29 #endif
30 #ifdef HAVE_UNISTD_H
31 # include <unistd.h>
32 #endif
33
34 #include "ntstatus.h"
35 #define WIN32_NO_STATUS
36 #include "wine/debug.h"
37 #include "windef.h"
38 #include "winternl.h"
39 #include "ntdll_misc.h"
40 #include "wine/server.h"
41
42 WINE_DEFAULT_DEBUG_CHANNEL(ntdll);
43
44
45 /*
46  *      Generic object functions
47  */
48
49 /******************************************************************************
50  * NtQueryObject [NTDLL.@]
51  * ZwQueryObject [NTDLL.@]
52  */
53 NTSTATUS WINAPI NtQueryObject(IN HANDLE handle,
54                               IN OBJECT_INFORMATION_CLASS info_class,
55                               OUT PVOID ptr, IN ULONG len, OUT PULONG used_len)
56 {
57     NTSTATUS status;
58
59     TRACE("(%p,0x%08x,%p,0x%08x,%p): stub\n",
60           handle, info_class, ptr, len, used_len);
61
62     if (used_len) *used_len = 0;
63
64     switch (info_class)
65     {
66     case ObjectBasicInformation:
67         {
68             POBJECT_BASIC_INFORMATION p = (POBJECT_BASIC_INFORMATION)ptr;
69
70             if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
71
72             SERVER_START_REQ( get_object_info )
73             {
74                 req->handle = handle;
75                 status = wine_server_call( req );
76                 if (status == STATUS_SUCCESS)
77                 {
78                     memset( p, 0, sizeof(*p) );
79                     p->GrantedAccess = reply->access;
80                     p->PointerCount = reply->ref_count;
81                     p->HandleCount = 1; /* at least one */
82                     if (used_len) *used_len = sizeof(*p);
83                 }
84             }
85             SERVER_END_REQ;
86         }
87         break;
88     case ObjectDataInformation:
89         {
90             OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;
91
92             if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
93
94             SERVER_START_REQ( set_handle_info )
95             {
96                 req->handle = handle;
97                 req->flags  = 0;
98                 req->mask   = 0;
99                 status = wine_server_call( req );
100                 if (status == STATUS_SUCCESS)
101                 {
102                     p->InheritHandle = (reply->old_flags & HANDLE_FLAG_INHERIT) ? TRUE : FALSE;
103                     p->ProtectFromClose = (reply->old_flags & HANDLE_FLAG_PROTECT_FROM_CLOSE) ? TRUE : FALSE;
104                     if (used_len) *used_len = sizeof(*p);
105                 }
106             }
107             SERVER_END_REQ;
108         }
109         break;
110     default:
111         FIXME("Unsupported information class %u\n", info_class);
112         status = STATUS_NOT_IMPLEMENTED;
113         break;
114     }
115     return status;
116 }
117
118 /******************************************************************
119  *              NtSetInformationObject [NTDLL.@]
120  *              ZwSetInformationObject [NTDLL.@]
121  *
122  */
123 NTSTATUS WINAPI NtSetInformationObject(IN HANDLE handle,
124                                        IN OBJECT_INFORMATION_CLASS info_class,
125                                        IN PVOID ptr, IN ULONG len)
126 {
127     NTSTATUS status;
128
129     TRACE("(%p,0x%08x,%p,0x%08x): stub\n",
130           handle, info_class, ptr, len);
131
132     switch (info_class)
133     {
134     case ObjectDataInformation:
135         {
136             OBJECT_DATA_INFORMATION* p = (OBJECT_DATA_INFORMATION*)ptr;
137
138             if (len < sizeof(*p)) return STATUS_INVALID_BUFFER_SIZE;
139
140             SERVER_START_REQ( set_handle_info )
141             {
142                 req->handle = handle;
143                 req->flags  = 0;
144                 req->mask   = HANDLE_FLAG_INHERIT | HANDLE_FLAG_PROTECT_FROM_CLOSE;
145                 if (p->InheritHandle)    req->flags |= HANDLE_FLAG_INHERIT;
146                 if (p->ProtectFromClose) req->flags |= HANDLE_FLAG_PROTECT_FROM_CLOSE;
147                 status = wine_server_call( req );
148             }
149             SERVER_END_REQ;
150         }
151         break;
152     default:
153         FIXME("Unsupported information class %u\n", info_class);
154         status = STATUS_NOT_IMPLEMENTED;
155         break;
156     }
157     return status;
158 }
159
160 /******************************************************************************
161  *  NtQuerySecurityObject       [NTDLL.@]
162  *
163  * An ntdll analogue to GetKernelObjectSecurity().
164  *
165  */
166 NTSTATUS WINAPI
167 NtQuerySecurityObject(
168         IN HANDLE Object,
169         IN SECURITY_INFORMATION RequestedInformation,
170         OUT PSECURITY_DESCRIPTOR pSecurityDescriptor,
171         IN ULONG Length,
172         OUT PULONG ResultLength)
173 {
174     PISECURITY_DESCRIPTOR_RELATIVE psd = pSecurityDescriptor;
175     NTSTATUS status;
176     unsigned int buffer_size = 512;
177     BOOLEAN need_more_memory = FALSE;
178
179     TRACE("(%p,0x%08x,%p,0x%08x,%p)\n",
180         Object, RequestedInformation, pSecurityDescriptor, Length, ResultLength);
181
182     do
183     {
184         char *buffer = RtlAllocateHeap(GetProcessHeap(), 0, buffer_size);
185         if (!buffer)
186             return STATUS_NO_MEMORY;
187
188         SERVER_START_REQ( get_security_object )
189         {
190             req->handle = Object;
191             req->security_info = RequestedInformation;
192             wine_server_set_reply( req, buffer, buffer_size );
193             status = wine_server_call( req );
194             if (status == STATUS_SUCCESS)
195             {
196                 struct security_descriptor *sd = (struct security_descriptor *)buffer;
197                 if (reply->sd_len)
198                 {
199                     *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE) +
200                         sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len;
201                     if (Length >= *ResultLength)
202                     {
203                         psd->Revision = SECURITY_DESCRIPTOR_REVISION;
204                         psd->Sbz1 = 0;
205                         psd->Control = sd->control | SE_SELF_RELATIVE;
206                         psd->Owner = sd->owner_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) : 0;
207                         psd->Group = sd->group_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len : 0;
208                         psd->Sacl = sd->sacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len : 0;
209                         psd->Dacl = sd->dacl_len ? sizeof(SECURITY_DESCRIPTOR_RELATIVE) + sd->owner_len + sd->group_len + sd->sacl_len : 0;
210                         /* owner, group, sacl and dacl are the same type as in the server
211                          * and in the same order so we copy the memory in one block */
212                         memcpy((char *)pSecurityDescriptor + sizeof(SECURITY_DESCRIPTOR_RELATIVE),
213                                buffer + sizeof(struct security_descriptor),
214                                sd->owner_len + sd->group_len + sd->sacl_len + sd->dacl_len);
215                     }
216                     else
217                         status = STATUS_BUFFER_TOO_SMALL;
218                 }
219                 else
220                 {
221                     *ResultLength = sizeof(SECURITY_DESCRIPTOR_RELATIVE);
222                     if (Length >= *ResultLength)
223                     {
224                         memset(psd, 0, sizeof(*psd));
225                         psd->Revision = SECURITY_DESCRIPTOR_REVISION;
226                         psd->Control = SE_SELF_RELATIVE;
227                     }
228                     else
229                         status = STATUS_BUFFER_TOO_SMALL;
230                 }
231             }
232             else if (status == STATUS_BUFFER_TOO_SMALL)
233             {
234                 buffer_size = reply->sd_len;
235                 need_more_memory = TRUE;
236             }
237         }
238         SERVER_END_REQ;
239         RtlFreeHeap(GetProcessHeap(), 0, buffer);
240     } while (need_more_memory);
241
242     return status;
243 }
244
245
246 /******************************************************************************
247  *  NtDuplicateObject           [NTDLL.@]
248  *  ZwDuplicateObject           [NTDLL.@]
249  */
250 NTSTATUS WINAPI NtDuplicateObject( HANDLE source_process, HANDLE source,
251                                    HANDLE dest_process, PHANDLE dest,
252                                    ACCESS_MASK access, ULONG attributes, ULONG options )
253 {
254     NTSTATUS ret;
255     SERVER_START_REQ( dup_handle )
256     {
257         req->src_process = source_process;
258         req->src_handle  = source;
259         req->dst_process = dest_process;
260         req->access      = access;
261         req->attributes  = attributes;
262         req->options     = options;
263
264         if (!(ret = wine_server_call( req )))
265         {
266             if (dest) *dest = reply->handle;
267             if (reply->closed)
268             {
269                 if (reply->self)
270                 {
271                     int fd = server_remove_fd_from_cache( source );
272                     if (fd != -1) close( fd );
273                 }
274             }
275             else if (options & DUPLICATE_CLOSE_SOURCE)
276                 WARN( "failed to close handle %p in process %p\n", source, source_process );
277         }
278     }
279     SERVER_END_REQ;
280     return ret;
281 }
282
283 /**************************************************************************
284  *                 NtClose                              [NTDLL.@]
285  *
286  * Close a handle reference to an object.
287  * 
288  * PARAMS
289  *  Handle [I] handle to close
290  *
291  * RETURNS
292  *  Success: ERROR_SUCCESS.
293  *  Failure: An NTSTATUS error code.
294  */
295 NTSTATUS WINAPI NtClose( HANDLE Handle )
296 {
297     NTSTATUS ret;
298     int fd = server_remove_fd_from_cache( Handle );
299
300     SERVER_START_REQ( close_handle )
301     {
302         req->handle = Handle;
303         ret = wine_server_call( req );
304     }
305     SERVER_END_REQ;
306     if (fd != -1) close( fd );
307     return ret;
308 }
309
310 /*
311  *      Directory functions
312  */
313
314 /**************************************************************************
315  * NtOpenDirectoryObject [NTDLL.@]
316  * ZwOpenDirectoryObject [NTDLL.@]
317  *
318  * Open a namespace directory object.
319  * 
320  * PARAMS
321  *  DirectoryHandle  [O] Destination for the new directory handle
322  *  DesiredAccess    [I] Desired access to the directory
323  *  ObjectAttributes [I] Structure describing the directory
324  *
325  * RETURNS
326  *  Success: ERROR_SUCCESS.
327  *  Failure: An NTSTATUS error code.
328  */
329 NTSTATUS WINAPI NtOpenDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
330                                       POBJECT_ATTRIBUTES ObjectAttributes)
331 {
332     NTSTATUS ret;
333     TRACE("(%p,0x%08x)\n", DirectoryHandle, DesiredAccess);
334     dump_ObjectAttributes(ObjectAttributes);
335
336     if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
337     if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
338     /* Have to test it here because server won't know difference between
339      * ObjectName == NULL and ObjectName == "" */
340     if (!ObjectAttributes->ObjectName)
341     {
342         if (ObjectAttributes->RootDirectory)
343             return STATUS_OBJECT_NAME_INVALID;
344         else
345             return STATUS_OBJECT_PATH_SYNTAX_BAD;
346     }
347
348     SERVER_START_REQ(open_directory)
349     {
350         req->access = DesiredAccess;
351         req->attributes = ObjectAttributes->Attributes;
352         req->rootdir = ObjectAttributes->RootDirectory;
353         if (ObjectAttributes->ObjectName)
354             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
355                                  ObjectAttributes->ObjectName->Length);
356         ret = wine_server_call( req );
357         *DirectoryHandle = reply->handle;
358     }
359     SERVER_END_REQ;
360     return ret;
361 }
362
363 /******************************************************************************
364  *  NtCreateDirectoryObject     [NTDLL.@]
365  *  ZwCreateDirectoryObject     [NTDLL.@]
366  *
367  * Create a namespace directory object.
368  * 
369  * PARAMS
370  *  DirectoryHandle  [O] Destination for the new directory handle
371  *  DesiredAccess    [I] Desired access to the directory
372  *  ObjectAttributes [I] Structure describing the directory
373  *
374  * RETURNS
375  *  Success: ERROR_SUCCESS.
376  *  Failure: An NTSTATUS error code.
377  */
378 NTSTATUS WINAPI NtCreateDirectoryObject(PHANDLE DirectoryHandle, ACCESS_MASK DesiredAccess,
379                                         POBJECT_ATTRIBUTES ObjectAttributes)
380 {
381     NTSTATUS ret;
382     TRACE("(%p,0x%08x)\n", DirectoryHandle, DesiredAccess);
383     dump_ObjectAttributes(ObjectAttributes);
384
385     if (!DirectoryHandle) return STATUS_ACCESS_VIOLATION;
386
387     SERVER_START_REQ(create_directory)
388     {
389         req->access = DesiredAccess;
390         req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
391         req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
392         if (ObjectAttributes && ObjectAttributes->ObjectName)
393             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
394                                  ObjectAttributes->ObjectName->Length);
395         ret = wine_server_call( req );
396         *DirectoryHandle = reply->handle;
397     }
398     SERVER_END_REQ;
399     return ret;
400 }
401
402 /******************************************************************************
403  * NtQueryDirectoryObject [NTDLL.@]
404  * ZwQueryDirectoryObject [NTDLL.@]
405  *
406  * Read information from a namespace directory.
407  * 
408  * PARAMS
409  *  DirectoryHandle   [I]   Handle to a directory object
410  *  Buffer            [O]   Buffer to hold the read data
411  *  BufferLength      [I]   Size of the buffer in bytes
412  *  ReturnSingleEntry [I]   If TRUE, return a single entry, if FALSE, return as many as fit in the buffer
413  *  RestartScan       [I]   If TRUE, start scanning from the start, if FALSE, scan from Context
414  *  Context           [I/O] Indicates what point of the directory the scan is at
415  *  ReturnLength      [O]   Caller supplied storage for the number of bytes written (or NULL)
416  *
417  * RETURNS
418  *  Success: ERROR_SUCCESS.
419  *  Failure: An NTSTATUS error code.
420  */
421 NTSTATUS WINAPI NtQueryDirectoryObject(IN HANDLE DirectoryHandle, OUT PDIRECTORY_BASIC_INFORMATION Buffer,
422                                        IN ULONG BufferLength, IN BOOLEAN ReturnSingleEntry, IN BOOLEAN RestartScan,
423                                        IN OUT PULONG Context, OUT PULONG ReturnLength OPTIONAL)
424 {
425     FIXME("(%p,%p,0x%08x,0x%08x,0x%08x,%p,%p), stub\n", DirectoryHandle, Buffer, BufferLength, ReturnSingleEntry,
426           RestartScan, Context, ReturnLength);
427
428     return STATUS_NOT_IMPLEMENTED;
429 }
430
431 /*
432  *      Link objects
433  */
434
435 /******************************************************************************
436  *  NtOpenSymbolicLinkObject    [NTDLL.@]
437  *  ZwOpenSymbolicLinkObject    [NTDLL.@]
438  *
439  * Open a namespace symbolic link object.
440  * 
441  * PARAMS
442  *  LinkHandle       [O] Destination for the new symbolic link handle
443  *  DesiredAccess    [I] Desired access to the symbolic link
444  *  ObjectAttributes [I] Structure describing the symbolic link
445  *
446  * RETURNS
447  *  Success: ERROR_SUCCESS.
448  *  Failure: An NTSTATUS error code.
449  */
450 NTSTATUS WINAPI NtOpenSymbolicLinkObject(OUT PHANDLE LinkHandle, IN ACCESS_MASK DesiredAccess,
451                                          IN POBJECT_ATTRIBUTES ObjectAttributes)
452 {
453     NTSTATUS ret;
454     TRACE("(%p,0x%08x,%p)\n",LinkHandle, DesiredAccess, ObjectAttributes);
455     dump_ObjectAttributes(ObjectAttributes);
456
457     if (!LinkHandle) return STATUS_ACCESS_VIOLATION;
458     if (!ObjectAttributes) return STATUS_INVALID_PARAMETER;
459     /* Have to test it here because server won't know difference between
460      * ObjectName == NULL and ObjectName == "" */
461     if (!ObjectAttributes->ObjectName)
462     {
463         if (ObjectAttributes->RootDirectory)
464             return STATUS_OBJECT_NAME_INVALID;
465         else
466             return STATUS_OBJECT_PATH_SYNTAX_BAD;
467     }
468
469     SERVER_START_REQ(open_symlink)
470     {
471         req->access = DesiredAccess;
472         req->attributes = ObjectAttributes->Attributes;
473         req->rootdir = ObjectAttributes->RootDirectory;
474         if (ObjectAttributes->ObjectName)
475             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
476                                  ObjectAttributes->ObjectName->Length);
477         ret = wine_server_call( req );
478         *LinkHandle = reply->handle;
479     }
480     SERVER_END_REQ;
481     return ret;
482 }
483
484 /******************************************************************************
485  *  NtCreateSymbolicLinkObject  [NTDLL.@]
486  *  ZwCreateSymbolicLinkObject  [NTDLL.@]
487  *
488  * Open a namespace symbolic link object.
489  * 
490  * PARAMS
491  *  SymbolicLinkHandle [O] Destination for the new symbolic link handle
492  *  DesiredAccess      [I] Desired access to the symbolic link
493  *  ObjectAttributes   [I] Structure describing the symbolic link
494  *  TargetName         [I] Name of the target symbolic link points to
495  *
496  * RETURNS
497  *  Success: ERROR_SUCCESS.
498  *  Failure: An NTSTATUS error code.
499  */
500 NTSTATUS WINAPI NtCreateSymbolicLinkObject(OUT PHANDLE SymbolicLinkHandle,IN ACCESS_MASK DesiredAccess,
501                                            IN POBJECT_ATTRIBUTES ObjectAttributes,
502                                            IN PUNICODE_STRING TargetName)
503 {
504     NTSTATUS ret;
505     TRACE("(%p,0x%08x,%p, -> %s)\n", SymbolicLinkHandle, DesiredAccess, ObjectAttributes,
506                                       debugstr_us(TargetName));
507     dump_ObjectAttributes(ObjectAttributes);
508
509     if (!SymbolicLinkHandle || !TargetName) return STATUS_ACCESS_VIOLATION;
510     if (!TargetName->Buffer) return STATUS_INVALID_PARAMETER;
511
512     SERVER_START_REQ(create_symlink)
513     {
514         req->access = DesiredAccess;
515         req->attributes = ObjectAttributes ? ObjectAttributes->Attributes : 0;
516         req->rootdir = ObjectAttributes ? ObjectAttributes->RootDirectory : 0;
517         if (ObjectAttributes && ObjectAttributes->ObjectName)
518         {
519             req->name_len = ObjectAttributes->ObjectName->Length;
520             wine_server_add_data(req, ObjectAttributes->ObjectName->Buffer,
521                                  ObjectAttributes->ObjectName->Length);
522         }
523         else
524             req->name_len = 0;
525         wine_server_add_data(req, TargetName->Buffer, TargetName->Length);
526         ret = wine_server_call( req );
527         *SymbolicLinkHandle = reply->handle;
528     }
529     SERVER_END_REQ;
530     return ret;
531 }
532
533 /******************************************************************************
534  *  NtQuerySymbolicLinkObject   [NTDLL.@]
535  *  ZwQuerySymbolicLinkObject   [NTDLL.@]
536  *
537  * Query a namespace symbolic link object target name.
538  * 
539  * PARAMS
540  *  LinkHandle     [I] Handle to a symbolic link object
541  *  LinkTarget     [O] Destination for the symbolic link target
542  *  ReturnedLength [O] Size of returned data
543  *
544  * RETURNS
545  *  Success: ERROR_SUCCESS.
546  *  Failure: An NTSTATUS error code.
547  */
548 NTSTATUS WINAPI NtQuerySymbolicLinkObject(IN HANDLE LinkHandle, IN OUT PUNICODE_STRING LinkTarget,
549                                           OUT PULONG ReturnedLength OPTIONAL)
550 {
551     NTSTATUS ret;
552     TRACE("(%p,%p,%p)\n", LinkHandle, LinkTarget, ReturnedLength);
553
554     if (!LinkTarget) return STATUS_ACCESS_VIOLATION;
555
556     SERVER_START_REQ(query_symlink)
557     {
558         req->handle = LinkHandle;
559         wine_server_set_reply( req, LinkTarget->Buffer, LinkTarget->MaximumLength );
560         if (!(ret = wine_server_call( req )))
561         {
562             LinkTarget->Length = wine_server_reply_size(reply);
563             if (ReturnedLength) *ReturnedLength = LinkTarget->Length;
564         }
565     }
566     SERVER_END_REQ;
567     return ret;
568 }
569
570 /******************************************************************************
571  *  NtAllocateUuids   [NTDLL.@]
572  */
573 NTSTATUS WINAPI NtAllocateUuids(
574         PULARGE_INTEGER Time,
575         PULONG Range,
576         PULONG Sequence)
577 {
578         FIXME("(%p,%p,%p), stub.\n", Time, Range, Sequence);
579         return 0;
580 }