Release 980215
[wine/multimedia.git] / scheduler / handle.c
blob6c1d6416147e96b55b828c943e2138681ff58d30
1 /*
2 * Win32 process handles
4 * Copyright 1998 Alexandre Julliard
5 */
7 #include <assert.h>
8 #include <stdio.h>
9 #include "winbase.h"
10 #include "winerror.h"
11 #include "heap.h"
12 #include "process.h"
14 #define HTABLE_SIZE 0x30 /* Handle table initial size */
15 #define HTABLE_INC 0x10 /* Handle table increment */
17 /* Reserved access rights */
18 #define RESERVED_ALL (0x0007 << RESERVED_SHIFT)
19 #define RESERVED_SHIFT 25
20 #define RESERVED_INHERIT (HANDLE_FLAG_INHERIT<<RESERVED_SHIFT)
21 #define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE<<RESERVED_SHIFT)
24 /***********************************************************************
25 * HANDLE_AllocTable
27 HANDLE_TABLE *HANDLE_AllocTable( PDB32 *process )
29 HANDLE_TABLE *table = HeapAlloc( process->system_heap, HEAP_ZERO_MEMORY,
30 sizeof(HANDLE_TABLE) +
31 (HTABLE_SIZE-1) * sizeof(HANDLE_ENTRY) );
32 if (!table) return NULL;
33 table->count = HTABLE_SIZE;
34 return table;
38 /***********************************************************************
39 * HANDLE_GrowTable
41 static BOOL32 HANDLE_GrowTable( PDB32 *process )
43 HANDLE_TABLE *table;
45 SYSTEM_LOCK();
46 table = process->handle_table;
47 table = HeapReAlloc( process->system_heap,
48 HEAP_ZERO_MEMORY | HEAP_NO_SERIALIZE, table,
49 sizeof(HANDLE_TABLE) +
50 (table->count+HTABLE_INC-1) * sizeof(HANDLE_ENTRY) );
51 if (table)
53 table->count += HTABLE_INC;
54 process->handle_table = table;
56 SYSTEM_UNLOCK();
57 return (table != NULL);
61 /***********************************************************************
62 * HANDLE_Alloc
64 * Allocate a handle for a kernel object and increment its refcount.
66 HANDLE32 HANDLE_Alloc( K32OBJ *ptr, DWORD access, BOOL32 inherit )
68 HANDLE32 h;
69 HANDLE_ENTRY *entry;
70 PDB32 *pdb = PROCESS_Current();
72 assert( ptr );
74 /* Set the inherit reserved flag */
75 access &= ~RESERVED_ALL;
76 if (inherit) access |= RESERVED_INHERIT;
78 SYSTEM_LOCK();
79 K32OBJ_IncCount( ptr );
80 entry = pdb->handle_table->entries;
81 for (h = 0; h < pdb->handle_table->count; h++, entry++)
82 if (!entry->ptr) break;
83 if ((h < pdb->handle_table->count) || HANDLE_GrowTable( pdb ))
85 entry = &pdb->handle_table->entries[h];
86 entry->access = access;
87 entry->ptr = ptr;
88 SYSTEM_UNLOCK();
89 return h + 1; /* Avoid handle 0 */
91 K32OBJ_DecCount( ptr );
92 SYSTEM_UNLOCK();
93 SetLastError( ERROR_OUTOFMEMORY );
94 return INVALID_HANDLE_VALUE32;
98 /***********************************************************************
99 * HANDLE_GetObjPtr
101 * Retrieve a pointer to a kernel object and increments its reference count.
102 * The refcount must be decremented when the pointer is no longer used.
104 K32OBJ *HANDLE_GetObjPtr( HANDLE32 handle, K32OBJ_TYPE type, DWORD access )
106 K32OBJ *ptr = NULL;
107 PDB32 *pdb = PROCESS_Current();
109 SYSTEM_LOCK();
110 if ((handle > 0) && (handle <= pdb->handle_table->count))
112 HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle-1];
113 if ((entry->access & access) != access)
114 fprintf( stderr, "Warning: handle %08x bad access (acc=%08lx req=%08lx)\n",
115 handle, entry->access, access );
116 ptr = entry->ptr;
117 if (ptr && ((type == K32OBJ_UNKNOWN) || (ptr->type == type)))
118 K32OBJ_IncCount( ptr );
119 else
120 ptr = NULL;
122 SYSTEM_UNLOCK();
123 if (!ptr) SetLastError( ERROR_INVALID_HANDLE );
124 return ptr;
128 /***********************************************************************
129 * HANDLE_SetObjPtr
131 * Change the object pointer of a handle, and increment the refcount.
132 * Use with caution!
134 BOOL32 HANDLE_SetObjPtr( HANDLE32 handle, K32OBJ *ptr, DWORD access )
136 BOOL32 ret = FALSE;
137 PDB32 *pdb = PROCESS_Current();
139 SYSTEM_LOCK();
140 if ((handle > 0) && (handle <= pdb->handle_table->count))
142 HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle-1];
143 K32OBJ *old_ptr = entry->ptr;
144 K32OBJ_IncCount( ptr );
145 entry->access = access;
146 entry->ptr = ptr;
147 if (old_ptr) K32OBJ_DecCount( old_ptr );
148 ret = TRUE;
150 SYSTEM_UNLOCK();
151 if (!ret) SetLastError( ERROR_INVALID_HANDLE );
152 return ret;
156 /*********************************************************************
157 * CloseHandle (KERNEL32.23)
159 BOOL32 WINAPI CloseHandle( HANDLE32 handle )
161 BOOL32 ret = FALSE;
162 PDB32 *pdb = PROCESS_Current();
163 K32OBJ *ptr;
165 SYSTEM_LOCK();
166 if ((handle > 0) && (handle <= pdb->handle_table->count))
168 HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle-1];
169 if ((ptr = entry->ptr))
171 if (!(entry->access & RESERVED_CLOSE_PROTECT))
173 entry->access = 0;
174 entry->ptr = NULL;
175 K32OBJ_DecCount( ptr );
176 ret = TRUE;
178 /* FIXME: else SetLastError */
181 SYSTEM_UNLOCK();
182 if (!ret) SetLastError( ERROR_INVALID_HANDLE );
183 return ret;
187 /*********************************************************************
188 * GetHandleInformation (KERNEL32.336)
190 BOOL32 WINAPI GetHandleInformation( HANDLE32 handle, LPDWORD flags )
192 BOOL32 ret = FALSE;
193 PDB32 *pdb = PROCESS_Current();
195 SYSTEM_LOCK();
196 if ((handle > 0) && (handle <= pdb->handle_table->count))
198 HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle-1];
199 if (entry->ptr)
201 if (flags)
202 *flags = (entry->access & RESERVED_ALL) >> RESERVED_SHIFT;
203 ret = TRUE;
206 SYSTEM_UNLOCK();
207 if (!ret) SetLastError( ERROR_INVALID_HANDLE );
208 return ret;
212 /*********************************************************************
213 * SetHandleInformation (KERNEL32.653)
215 BOOL32 WINAPI SetHandleInformation( HANDLE32 handle, DWORD mask, DWORD flags )
217 BOOL32 ret = FALSE;
218 PDB32 *pdb = PROCESS_Current();
220 mask = (mask << RESERVED_SHIFT) & RESERVED_ALL;
221 flags = (flags << RESERVED_SHIFT) & RESERVED_ALL;
222 SYSTEM_LOCK();
223 if ((handle > 0) && (handle <= pdb->handle_table->count))
225 HANDLE_ENTRY *entry = &pdb->handle_table->entries[handle-1];
226 if (entry->ptr)
228 entry->access = (entry->access & ~mask) | flags;
229 ret = TRUE;
232 SYSTEM_UNLOCK();
233 if (!ret) SetLastError( ERROR_INVALID_HANDLE );
234 return ret;