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