Take into account handle inheritance flag.
[wine] / scheduler / k32obj.c
1 /*
2  * KERNEL32 objects
3  *
4  * Copyright 1996 Alexandre Julliard
5  */
6
7 #include <assert.h>
8 #include "winerror.h"
9 #include "k32obj.h"
10 #include "heap.h"
11 #include "process.h"
12
13
14 /* The declarations are here to avoid including a lot of unnecessary files */
15 extern const K32OBJ_OPS PROCESS_Ops;
16 extern const K32OBJ_OPS THREAD_Ops;
17 extern const K32OBJ_OPS FILE_Ops;
18 extern const K32OBJ_OPS CHANGE_Ops;
19 extern const K32OBJ_OPS MEM_MAPPED_FILE_Ops;
20 extern const K32OBJ_OPS DEVICE_Ops;
21 extern const K32OBJ_OPS CONSOLE_Ops;
22 extern const K32OBJ_OPS SNAPSHOT_Ops;
23
24 /* The following are fully implemented in the server and could be removed */
25 extern const K32OBJ_OPS SEMAPHORE_Ops;
26 extern const K32OBJ_OPS EVENT_Ops;
27 extern const K32OBJ_OPS MUTEX_Ops;
28 extern const K32OBJ_OPS PIPE_Ops;
29
30 static const K32OBJ_OPS K32OBJ_NullOps =
31 {
32     NULL     /* destroy */
33 };
34
35 const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] =
36 {
37     NULL,
38     &SEMAPHORE_Ops,         /* K32OBJ_SEMAPHORE */
39     &EVENT_Ops,             /* K32OBJ_EVENT */
40     &MUTEX_Ops,             /* K32OBJ_MUTEX */
41     &K32OBJ_NullOps,        /* K32OBJ_CRITICAL_SECTION */
42     &PROCESS_Ops,           /* K32OBJ_PROCESS */
43     &THREAD_Ops,            /* K32OBJ_THREAD */
44     &FILE_Ops,              /* K32OBJ_FILE */
45     &CHANGE_Ops,            /* K32OBJ_CHANGE */
46     &CONSOLE_Ops,           /* K32OBJ_CONSOLE */
47     &K32OBJ_NullOps,        /* K32OBJ_SCREEN_BUFFER */
48     &MEM_MAPPED_FILE_Ops,   /* K32OBJ_MEM_MAPPED_FILE */
49     &K32OBJ_NullOps,        /* K32OBJ_SERIAL */
50     &DEVICE_Ops,            /* K32OBJ_DEVICE_IOCTL */
51     &PIPE_Ops,              /* K32OBJ_PIPE */
52     &K32OBJ_NullOps,        /* K32OBJ_MAILSLOT */
53     &K32OBJ_NullOps,        /* K32OBJ_TOOLHELP_SNAPSHOT */
54     &K32OBJ_NullOps         /* K32OBJ_SOCKET */
55 };
56
57 typedef struct _NE
58 {
59     struct _NE *next;
60     K32OBJ     *obj;
61     UINT32      len;
62     char        name[1];
63 } NAME_ENTRY;
64
65 static NAME_ENTRY *K32OBJ_FirstEntry = NULL;
66
67
68 /***********************************************************************
69  *           K32OBJ_IncCount
70  */
71 void K32OBJ_IncCount( K32OBJ *ptr )
72 {
73     assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
74     SYSTEM_LOCK();
75     ptr->refcount++;
76     SYSTEM_UNLOCK();
77     assert( ptr->refcount > 0 );  /* No wrap-around allowed */
78 }
79
80
81 /***********************************************************************
82  *           K32OBJ_DecCount
83  */
84 void K32OBJ_DecCount( K32OBJ *ptr )
85 {
86     NAME_ENTRY **pptr;
87
88     assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
89     assert( ptr->refcount > 0 );
90     SYSTEM_LOCK();
91     if (--ptr->refcount)
92     {
93         SYSTEM_UNLOCK();
94         return;
95     }
96
97     /* Check if the object has a name entry and free it */
98
99     pptr = &K32OBJ_FirstEntry;
100     while (*pptr && ((*pptr)->obj != ptr)) pptr = &(*pptr)->next;
101     if (*pptr)
102     {
103         NAME_ENTRY *entry = *pptr;
104         *pptr = entry->next;
105         HeapFree( SystemHeap, 0, entry );
106     }
107
108     /* Free the object */
109
110     if (K32OBJ_Ops[ptr->type]->destroy) K32OBJ_Ops[ptr->type]->destroy( ptr );
111     SYSTEM_UNLOCK();
112 }
113
114
115 /***********************************************************************
116  *           K32OBJ_IsValid
117  *
118  * Check if a pointer is a valid kernel object
119  */
120 BOOL32 K32OBJ_IsValid( K32OBJ *ptr, K32OBJ_TYPE type )
121 {
122     if (IsBadReadPtr32( ptr, sizeof(*ptr) )) return FALSE;
123     return (ptr->type == type);
124 }
125
126
127 /***********************************************************************
128  *           K32OBJ_AddName
129  *
130  * Add a name entry for an object. We don't check for duplicates here.
131  * FIXME: should use some sort of hashing.
132  */
133 BOOL32 K32OBJ_AddName( K32OBJ *obj, LPCSTR name )
134 {
135     NAME_ENTRY *entry;
136     UINT32 len;
137
138     if (!name) return TRUE;  /* Anonymous object */
139     len = strlen( name );
140     SYSTEM_LOCK();
141     if (!(entry = HeapAlloc( SystemHeap, 0, sizeof(NAME_ENTRY) + len )))
142     {
143         SYSTEM_UNLOCK();
144         SetLastError( ERROR_OUTOFMEMORY );
145         return FALSE;
146     }
147     entry->next = K32OBJ_FirstEntry;
148     entry->obj  = obj;
149     entry->len  = len;
150     lstrcpy32A( entry->name, name );
151     K32OBJ_FirstEntry = entry;
152     SYSTEM_UNLOCK();
153     return TRUE;
154 }
155
156
157 /***********************************************************************
158  *           K32OBJ_Create
159  *
160  * Create a named kernel object.
161  * Returns NULL if there was an error _or_ if the object already existed.
162  * The refcount of the object must be decremented once it is initialized.
163  */
164 K32OBJ *K32OBJ_Create( K32OBJ_TYPE type, DWORD size, LPCSTR name, int server_handle,
165                        DWORD access, SECURITY_ATTRIBUTES *sa, HANDLE32 *handle)
166 {
167     BOOL32 inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
168
169     /* Check if the name already exists */
170
171     K32OBJ *obj = K32OBJ_FindName( name );
172     if (obj)
173     {
174         if (obj->type == type)
175         {
176             SetLastError( ERROR_ALREADY_EXISTS );
177             *handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, server_handle );
178         }
179         else
180         {
181             SetLastError( ERROR_DUP_NAME );
182             *handle = INVALID_HANDLE_VALUE32;
183             if (server_handle != -1) CLIENT_CloseHandle( server_handle );
184         }
185         K32OBJ_DecCount( obj );
186         return NULL;
187     }
188
189     /* Create the object */
190
191     SYSTEM_LOCK();
192     if (!(obj = HeapAlloc( SystemHeap, 0, size )))
193     {
194         SYSTEM_UNLOCK();
195         *handle = INVALID_HANDLE_VALUE32;
196         if (server_handle != -1) CLIENT_CloseHandle( server_handle );
197         return NULL;
198     }
199     obj->type     = type;
200     obj->refcount = 1;
201
202     /* Add a name for it */
203
204     if (!K32OBJ_AddName( obj, name ))
205     {
206         /* Don't call the destroy function, as the object wasn't
207          * initialized properly */
208         HeapFree( SystemHeap, 0, obj );
209         SYSTEM_UNLOCK();
210         *handle = INVALID_HANDLE_VALUE32;
211         if (server_handle != -1) CLIENT_CloseHandle( server_handle );
212         return NULL;
213     }
214
215     /* Allocate a handle */
216
217     *handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, server_handle );
218     SYSTEM_UNLOCK();
219     return obj;
220 }
221
222
223 /***********************************************************************
224  *           K32OBJ_FindName
225  *
226  * Find the object referenced by a given name.
227  * The reference count is incremented.
228  */
229 K32OBJ *K32OBJ_FindName( LPCSTR name )
230 {
231     NAME_ENTRY *entry;
232     UINT32 len;
233
234     if (!name) return NULL;  /* Anonymous object */
235     len = strlen( name );
236     SYSTEM_LOCK();
237     entry = K32OBJ_FirstEntry;
238     while (entry)
239     {
240         if ((len == entry->len) && !strcmp( name, entry->name))
241         {
242             K32OBJ *obj = entry->obj;
243             K32OBJ_IncCount( obj );
244             SYSTEM_UNLOCK();
245             return entry->obj;
246         }
247         entry = entry->next;
248     }
249     SYSTEM_UNLOCK();
250     return NULL;
251 }
252
253
254 /***********************************************************************
255  *           K32OBJ_FindNameType
256  *
257  * Find an object by name and check its type.
258  * The reference count is incremented.
259  */
260 K32OBJ *K32OBJ_FindNameType( LPCSTR name, K32OBJ_TYPE type )
261 {
262     K32OBJ *obj = K32OBJ_FindName( name );
263     if (!obj) return NULL;
264     if (obj->type == type) return obj;
265     SetLastError( ERROR_DUP_NAME );
266     K32OBJ_DecCount( obj );
267     return NULL;
268 }