2 * Win32 process handles
4 * Copyright 1998 Alexandre Julliard
16 #define HTABLE_SIZE 0x30 /* Handle table initial size */
17 #define HTABLE_INC 0x10 /* Handle table increment */
19 /* Reserved access rights */
20 #define RESERVED_ALL (0x0007 << RESERVED_SHIFT)
21 #define RESERVED_SHIFT 25
22 #define RESERVED_INHERIT (HANDLE_FLAG_INHERIT<<RESERVED_SHIFT)
23 #define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE<<RESERVED_SHIFT)
26 /***********************************************************************
29 static BOOL32
HANDLE_GrowTable( PDB32
*process
, INT32 incr
)
34 table
= process
->handle_table
;
35 table
= HeapReAlloc( process
->system_heap
,
36 HEAP_ZERO_MEMORY
| HEAP_NO_SERIALIZE
, table
,
37 sizeof(HANDLE_TABLE
) +
38 (table
->count
+ incr
- 1) * sizeof(HANDLE_ENTRY
) );
42 process
->handle_table
= table
;
45 return (table
!= NULL
);
49 /***********************************************************************
52 * Create a process handle table, optionally inheriting the parent's handles.
54 BOOL32
HANDLE_CreateTable( PDB32
*pdb
, BOOL32 inherit
)
58 /* Process must not already have a handle table */
59 assert( !pdb
->handle_table
);
61 /* If this is the first process, simply allocate a table */
62 if (!pdb
->parent
) inherit
= FALSE
;
65 size
= inherit
? pdb
->parent
->handle_table
->count
: HTABLE_SIZE
;
66 if ((pdb
->handle_table
= HeapAlloc( pdb
->system_heap
,
67 HEAP_ZERO_MEMORY
| HEAP_NO_SERIALIZE
,
68 sizeof(HANDLE_TABLE
) +
69 (size
-1) * sizeof(HANDLE_ENTRY
) )))
71 pdb
->handle_table
->count
= size
;
74 HANDLE_ENTRY
*src
= pdb
->parent
->handle_table
->entries
;
75 HANDLE_ENTRY
*dst
= pdb
->handle_table
->entries
;
78 for (h
= 0; h
< size
; h
++, src
++, dst
++)
80 /* Check if handle is valid and inheritable */
81 if (src
->ptr
&& (src
->access
& RESERVED_INHERIT
))
83 dst
->access
= src
->access
;
85 dst
->server
= src
->server
;
86 K32OBJ_IncCount( dst
->ptr
);
90 /* Handle 1 is the process itself (unless the parent decided otherwise) */
91 if (!pdb
->handle_table
->entries
[1].ptr
)
93 pdb
->handle_table
->entries
[1].ptr
= &pdb
->header
;
94 pdb
->handle_table
->entries
[1].access
= PROCESS_ALL_ACCESS
;
95 pdb
->handle_table
->entries
[1].server
= -1; /* FIXME */
96 K32OBJ_IncCount( &pdb
->header
);
100 return (pdb
->handle_table
!= NULL
);
104 /***********************************************************************
107 * Allocate a handle for a kernel object and increment its refcount.
109 HANDLE32
HANDLE_Alloc( PDB32
*pdb
, K32OBJ
*ptr
, DWORD access
,
110 BOOL32 inherit
, int server_handle
)
117 /* Set the inherit reserved flag */
118 access
&= ~RESERVED_ALL
;
119 if (inherit
) access
|= RESERVED_INHERIT
;
122 K32OBJ_IncCount( ptr
);
123 /* Don't try to allocate handle 0 */
124 entry
= pdb
->handle_table
->entries
+ 1;
125 for (h
= 1; h
< pdb
->handle_table
->count
; h
++, entry
++)
126 if (!entry
->ptr
) break;
127 if ((h
< pdb
->handle_table
->count
) || HANDLE_GrowTable( pdb
, HTABLE_INC
))
129 entry
= &pdb
->handle_table
->entries
[h
];
130 entry
->access
= access
;
132 entry
->server
= server_handle
;
136 K32OBJ_DecCount( ptr
);
138 if (server_handle
!= -1) CLIENT_CloseHandle( server_handle
);
139 SetLastError( ERROR_OUTOFMEMORY
);
140 return INVALID_HANDLE_VALUE32
;
144 /***********************************************************************
147 * Retrieve a pointer to a kernel object and increments its reference count.
148 * The refcount must be decremented when the pointer is no longer used.
150 K32OBJ
*HANDLE_GetObjPtr( PDB32
*pdb
, HANDLE32 handle
,
151 K32OBJ_TYPE type
, DWORD access
,
157 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
159 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
];
160 if ((entry
->access
& access
) != access
)
161 WARN(win32
, "Handle %08x bad access (acc=%08lx req=%08lx)\n",
162 handle
, entry
->access
, access
);
164 if (server_handle
) *server_handle
= entry
->server
;
165 if (ptr
&& ((type
== K32OBJ_UNKNOWN
) || (ptr
->type
== type
)))
166 K32OBJ_IncCount( ptr
);
171 if (!ptr
) SetLastError( ERROR_INVALID_HANDLE
);
176 /***********************************************************************
179 * Change the object pointer of a handle, and increment the refcount.
182 BOOL32
HANDLE_SetObjPtr( PDB32
*pdb
, HANDLE32 handle
, K32OBJ
*ptr
,
188 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
190 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
];
191 K32OBJ
*old_ptr
= entry
->ptr
;
192 K32OBJ_IncCount( ptr
);
193 entry
->access
= access
;
195 if (old_ptr
) K32OBJ_DecCount( old_ptr
);
199 if (!ret
) SetLastError( ERROR_INVALID_HANDLE
);
204 /*********************************************************************
207 static BOOL32
HANDLE_GetAccess( PDB32
*pdb
, HANDLE32 handle
, LPDWORD access
)
212 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
214 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
];
217 *access
= entry
->access
& ~RESERVED_ALL
;
222 if (!ret
) SetLastError( ERROR_INVALID_HANDLE
);
227 /*********************************************************************
230 static BOOL32
HANDLE_Close( PDB32
*pdb
, HANDLE32 handle
)
236 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
238 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
];
239 if ((ptr
= entry
->ptr
))
241 if (!(entry
->access
& RESERVED_CLOSE_PROTECT
))
245 if (entry
->server
!= -1)
246 CLIENT_CloseHandle( entry
->server
);
247 K32OBJ_DecCount( ptr
);
250 /* FIXME: else SetLastError */
254 if (!ret
) SetLastError( ERROR_INVALID_HANDLE
);
259 /*********************************************************************
262 * Close all handles pointing to a given object (or all handles of the
263 * process if the object is NULL)
265 void HANDLE_CloseAll( PDB32
*pdb
, K32OBJ
*obj
)
272 entry
= pdb
->handle_table
->entries
;
273 for (handle
= 0; handle
< pdb
->handle_table
->count
; handle
++, entry
++)
275 if (!(ptr
= entry
->ptr
)) continue; /* empty slot */
276 if (obj
&& (ptr
!= obj
)) continue; /* not the right object */
279 if (entry
->server
!= -1) CLIENT_CloseHandle( entry
->server
);
280 K32OBJ_DecCount( ptr
);
286 /*********************************************************************
287 * CloseHandle (KERNEL32.23)
289 BOOL32 WINAPI
CloseHandle( HANDLE32 handle
)
291 return HANDLE_Close( PROCESS_Current(), handle
);
295 /*********************************************************************
296 * GetHandleInformation (KERNEL32.336)
298 BOOL32 WINAPI
GetHandleInformation( HANDLE32 handle
, LPDWORD flags
)
301 PDB32
*pdb
= PROCESS_Current();
304 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
306 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
];
310 *flags
= (entry
->access
& RESERVED_ALL
) >> RESERVED_SHIFT
;
315 if (!ret
) SetLastError( ERROR_INVALID_HANDLE
);
320 /*********************************************************************
321 * SetHandleInformation (KERNEL32.653)
323 BOOL32 WINAPI
SetHandleInformation( HANDLE32 handle
, DWORD mask
, DWORD flags
)
326 PDB32
*pdb
= PROCESS_Current();
328 mask
= (mask
<< RESERVED_SHIFT
) & RESERVED_ALL
;
329 flags
= (flags
<< RESERVED_SHIFT
) & RESERVED_ALL
;
331 if ((handle
> 0) && (handle
<= pdb
->handle_table
->count
))
333 HANDLE_ENTRY
*entry
= &pdb
->handle_table
->entries
[handle
];
336 entry
->access
= (entry
->access
& ~mask
) | flags
;
341 if (!ret
) SetLastError( ERROR_INVALID_HANDLE
);
346 /*********************************************************************
347 * DuplicateHandle (KERNEL32.192)
349 BOOL32 WINAPI
DuplicateHandle( HANDLE32 source_process
, HANDLE32 source
,
350 HANDLE32 dest_process
, HANDLE32
*dest
,
351 DWORD access
, BOOL32 inherit
, DWORD options
)
353 PDB32
*src_pdb
= NULL
, *dst_pdb
= NULL
;
357 int src_process
, src_handle
, dst_process
, dst_handle
;
361 if (!(src_pdb
= PROCESS_GetPtr( source_process
, PROCESS_DUP_HANDLE
, &src_process
)))
363 if (!(obj
= HANDLE_GetObjPtr( src_pdb
, source
, K32OBJ_UNKNOWN
, 0, &src_handle
)))
366 /* Now that we are sure the source is valid, handle the options */
368 if (options
& DUPLICATE_SAME_ACCESS
)
369 HANDLE_GetAccess( src_pdb
, source
, &access
);
370 if (options
& DUPLICATE_CLOSE_SOURCE
)
371 HANDLE_Close( src_pdb
, source
);
373 /* And duplicate the handle in the dest process */
375 if (!(dst_pdb
= PROCESS_GetPtr( dest_process
, PROCESS_DUP_HANDLE
, &dst_process
)))
378 if ((src_process
!= -1) && (src_handle
!= -1) && (dst_process
!= -1))
379 dst_handle
= CLIENT_DuplicateHandle( src_process
, src_handle
, dst_process
, -1,
380 access
, inherit
, options
);
384 if ((handle
= HANDLE_Alloc( dst_pdb
, obj
, access
, inherit
,
385 dst_handle
)) != INVALID_HANDLE_VALUE32
)
387 if (dest
) *dest
= handle
;
392 if (dst_pdb
) K32OBJ_DecCount( &dst_pdb
->header
);
393 if (obj
) K32OBJ_DecCount( obj
);
394 if (src_pdb
) K32OBJ_DecCount( &src_pdb
->header
);