Release 990226.
[wine/gsoc-2012-control.git] / scheduler / k32obj.c
blob1f6f991b235e19167fc506085ebf94f78abab267
1 /*
2 * KERNEL32 objects
4 * Copyright 1996 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include "winerror.h"
9 #include "k32obj.h"
10 #include "heap.h"
11 #include "process.h"
12 #include "server.h"
15 /* The declarations are here to avoid including a lot of unnecessary files */
16 extern const K32OBJ_OPS PROCESS_Ops;
17 extern const K32OBJ_OPS THREAD_Ops;
19 static const K32OBJ_OPS K32OBJ_NullOps =
21 NULL /* destroy */
24 static void K32OBJ_Destroy( K32OBJ *obj );
26 static const K32OBJ_OPS K32OBJ_DefaultOps =
28 K32OBJ_Destroy /* destroy */
32 const K32OBJ_OPS * const K32OBJ_Ops[K32OBJ_NBOBJECTS] =
34 NULL,
35 &K32OBJ_DefaultOps, /* K32OBJ_SEMAPHORE */
36 &K32OBJ_DefaultOps, /* K32OBJ_EVENT */
37 &K32OBJ_DefaultOps, /* K32OBJ_MUTEX */
38 &K32OBJ_NullOps, /* K32OBJ_CRITICAL_SECTION */
39 &PROCESS_Ops, /* K32OBJ_PROCESS */
40 &THREAD_Ops, /* K32OBJ_THREAD */
41 &K32OBJ_DefaultOps, /* K32OBJ_FILE */
42 &K32OBJ_DefaultOps, /* K32OBJ_CHANGE */
43 &K32OBJ_DefaultOps, /* K32OBJ_CONSOLE */
44 &K32OBJ_NullOps, /* K32OBJ_SCREEN_BUFFER */
45 &K32OBJ_DefaultOps, /* K32OBJ_MEM_MAPPED_FILE */
46 &K32OBJ_NullOps, /* K32OBJ_SERIAL */
47 &K32OBJ_NullOps, /* K32OBJ_DEVICE_IOCTL */
48 &K32OBJ_DefaultOps, /* K32OBJ_PIPE */
49 &K32OBJ_NullOps, /* K32OBJ_MAILSLOT */
50 &K32OBJ_DefaultOps, /* K32OBJ_TOOLHELP_SNAPSHOT */
51 &K32OBJ_NullOps /* K32OBJ_SOCKET */
54 typedef struct _NE
56 struct _NE *next;
57 K32OBJ *obj;
58 UINT len;
59 char name[1];
60 } NAME_ENTRY;
62 static NAME_ENTRY *K32OBJ_FirstEntry = NULL;
65 /***********************************************************************
66 * K32OBJ_IncCount
68 void K32OBJ_IncCount( K32OBJ *ptr )
70 assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
71 SYSTEM_LOCK();
72 ptr->refcount++;
73 SYSTEM_UNLOCK();
74 assert( ptr->refcount > 0 ); /* No wrap-around allowed */
78 /***********************************************************************
79 * K32OBJ_DecCount
81 void K32OBJ_DecCount( K32OBJ *ptr )
83 NAME_ENTRY **pptr;
85 assert( ptr->type && ((unsigned)ptr->type < K32OBJ_NBOBJECTS) );
86 assert( ptr->refcount > 0 );
87 SYSTEM_LOCK();
88 if (--ptr->refcount)
90 SYSTEM_UNLOCK();
91 return;
94 /* Check if the object has a name entry and free it */
96 pptr = &K32OBJ_FirstEntry;
97 while (*pptr && ((*pptr)->obj != ptr)) pptr = &(*pptr)->next;
98 if (*pptr)
100 NAME_ENTRY *entry = *pptr;
101 *pptr = entry->next;
102 HeapFree( SystemHeap, 0, entry );
105 /* Free the object */
107 if (K32OBJ_Ops[ptr->type]->destroy) K32OBJ_Ops[ptr->type]->destroy( ptr );
108 SYSTEM_UNLOCK();
112 /***********************************************************************
113 * K32OBJ_Destroy
115 * Generic destroy functions for objects that don't need any special treatment.
117 static void K32OBJ_Destroy( K32OBJ *obj )
119 obj->type = K32OBJ_UNKNOWN;
120 HeapFree( SystemHeap, 0, obj );
124 /***********************************************************************
125 * K32OBJ_IsValid
127 * Check if a pointer is a valid kernel object
129 BOOL K32OBJ_IsValid( K32OBJ *ptr, K32OBJ_TYPE type )
131 if (IsBadReadPtr( ptr, sizeof(*ptr) )) return FALSE;
132 return (ptr->type == type);
136 /***********************************************************************
137 * K32OBJ_AddName
139 * Add a name entry for an object. We don't check for duplicates here.
140 * FIXME: should use some sort of hashing.
142 BOOL K32OBJ_AddName( K32OBJ *obj, LPCSTR name )
144 NAME_ENTRY *entry;
145 UINT len;
147 if (!name) return TRUE; /* Anonymous object */
148 len = strlen( name );
149 SYSTEM_LOCK();
150 if (!(entry = HeapAlloc( SystemHeap, 0, sizeof(NAME_ENTRY) + len )))
152 SYSTEM_UNLOCK();
153 SetLastError( ERROR_OUTOFMEMORY );
154 return FALSE;
156 entry->next = K32OBJ_FirstEntry;
157 entry->obj = obj;
158 entry->len = len;
159 lstrcpyA( entry->name, name );
160 K32OBJ_FirstEntry = entry;
161 SYSTEM_UNLOCK();
162 return TRUE;
166 /***********************************************************************
167 * K32OBJ_Create
169 * Create a named kernel object.
170 * Returns NULL if there was an error _or_ if the object already existed.
171 * The refcount of the object must be decremented once it is initialized.
173 K32OBJ *K32OBJ_Create( K32OBJ_TYPE type, DWORD size, LPCSTR name, int server_handle,
174 DWORD access, SECURITY_ATTRIBUTES *sa, HANDLE *handle)
176 BOOL inherit = (sa && (sa->nLength>=sizeof(*sa)) && sa->bInheritHandle);
178 /* Check if the name already exists */
180 K32OBJ *obj = K32OBJ_FindName( name );
181 if (obj)
183 if (obj->type == type)
185 SetLastError( ERROR_ALREADY_EXISTS );
186 *handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, server_handle );
188 else
190 SetLastError( ERROR_DUP_NAME );
191 *handle = INVALID_HANDLE_VALUE;
192 if (server_handle != -1) CLIENT_CloseHandle( server_handle );
194 K32OBJ_DecCount( obj );
195 return NULL;
198 /* Create the object */
200 SYSTEM_LOCK();
201 if (!(obj = HeapAlloc( SystemHeap, 0, size )))
203 SYSTEM_UNLOCK();
204 *handle = INVALID_HANDLE_VALUE;
205 if (server_handle != -1) CLIENT_CloseHandle( server_handle );
206 return NULL;
208 obj->type = type;
209 obj->refcount = 1;
211 /* Add a name for it */
213 if (!K32OBJ_AddName( obj, name ))
215 /* Don't call the destroy function, as the object wasn't
216 * initialized properly */
217 HeapFree( SystemHeap, 0, obj );
218 SYSTEM_UNLOCK();
219 *handle = INVALID_HANDLE_VALUE;
220 if (server_handle != -1) CLIENT_CloseHandle( server_handle );
221 return NULL;
224 /* Allocate a handle */
226 *handle = HANDLE_Alloc( PROCESS_Current(), obj, access, inherit, server_handle );
227 SYSTEM_UNLOCK();
228 return obj;
232 /***********************************************************************
233 * K32OBJ_FindName
235 * Find the object referenced by a given name.
236 * The reference count is incremented.
238 K32OBJ *K32OBJ_FindName( LPCSTR name )
240 NAME_ENTRY *entry;
241 UINT len;
243 if (!name) return NULL; /* Anonymous object */
244 len = strlen( name );
245 SYSTEM_LOCK();
246 entry = K32OBJ_FirstEntry;
247 while (entry)
249 if ((len == entry->len) && !strcmp( name, entry->name))
251 K32OBJ *obj = entry->obj;
252 K32OBJ_IncCount( obj );
253 SYSTEM_UNLOCK();
254 return entry->obj;
256 entry = entry->next;
258 SYSTEM_UNLOCK();
259 return NULL;
263 /***********************************************************************
264 * K32OBJ_FindNameType
266 * Find an object by name and check its type.
267 * The reference count is incremented.
269 K32OBJ *K32OBJ_FindNameType( LPCSTR name, K32OBJ_TYPE type )
271 K32OBJ *obj = K32OBJ_FindName( name );
272 if (!obj) return NULL;
273 if (obj->type == type) return obj;
274 SetLastError( ERROR_DUP_NAME );
275 K32OBJ_DecCount( obj );
276 return NULL;