handle.c 28 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878
  1. /*
  2. * Server-side handle management
  3. *
  4. * Copyright (C) 1998 Alexandre Julliard
  5. *
  6. * This library is free software; you can redistribute it and/or
  7. * modify it under the terms of the GNU Lesser General Public
  8. * License as published by the Free Software Foundation; either
  9. * version 2.1 of the License, or (at your option) any later version.
  10. *
  11. * This library is distributed in the hope that it will be useful,
  12. * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13. * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  14. * Lesser General Public License for more details.
  15. *
  16. * You should have received a copy of the GNU Lesser General Public
  17. * License along with this library; if not, write to the Free Software
  18. * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
  19. */
  20. #include "config.h"
  21. #include "wine/port.h"
  22. #include <assert.h>
  23. #include <limits.h>
  24. #include <string.h>
  25. #include <stdarg.h>
  26. #include <stdio.h>
  27. #include <stdlib.h>
  28. #include "ntstatus.h"
  29. #define WIN32_NO_STATUS
  30. #include "windef.h"
  31. #include "winternl.h"
  32. #include "handle.h"
  33. #include "process.h"
  34. #include "thread.h"
  35. #include "security.h"
  36. #include "request.h"
  37. struct handle_entry
  38. {
  39. struct object *ptr; /* object */
  40. unsigned int access; /* access rights */
  41. };
  42. struct handle_table
  43. {
  44. struct object obj; /* object header */
  45. struct process *process; /* process owning this table */
  46. int count; /* number of allocated entries */
  47. int last; /* last used entry */
  48. int free; /* first entry that may be free */
  49. struct handle_entry *entries; /* handle entries */
  50. };
  51. static struct handle_table *global_table;
  52. /* reserved handle access rights */
  53. #define RESERVED_SHIFT 26
  54. #define RESERVED_INHERIT (HANDLE_FLAG_INHERIT << RESERVED_SHIFT)
  55. #define RESERVED_CLOSE_PROTECT (HANDLE_FLAG_PROTECT_FROM_CLOSE << RESERVED_SHIFT)
  56. #define RESERVED_ALL (RESERVED_INHERIT | RESERVED_CLOSE_PROTECT)
  57. #define MIN_HANDLE_ENTRIES 32
  58. #define MAX_HANDLE_ENTRIES 0x00ffffff
  59. /* handle to table index conversion */
  60. /* handles are a multiple of 4 under NT; handle 0 is not used */
  61. static inline obj_handle_t index_to_handle( int index )
  62. {
  63. return (obj_handle_t)((index + 1) << 2);
  64. }
  65. static inline int handle_to_index( obj_handle_t handle )
  66. {
  67. return (handle >> 2) - 1;
  68. }
  69. /* global handle conversion */
  70. #define HANDLE_OBFUSCATOR 0x544a4def
  71. static inline int handle_is_global( obj_handle_t handle)
  72. {
  73. return (handle ^ HANDLE_OBFUSCATOR) <= (MAX_HANDLE_ENTRIES << 2);
  74. }
  75. static inline obj_handle_t handle_local_to_global( obj_handle_t handle )
  76. {
  77. if (!handle) return 0;
  78. return handle ^ HANDLE_OBFUSCATOR;
  79. }
  80. static inline obj_handle_t handle_global_to_local( obj_handle_t handle )
  81. {
  82. return handle ^ HANDLE_OBFUSCATOR;
  83. }
  84. /* grab an object and increment its handle count */
  85. static struct object *grab_object_for_handle( struct object *obj )
  86. {
  87. obj->handle_count++;
  88. obj->ops->type->handle_count++;
  89. obj->ops->type->handle_max = max( obj->ops->type->handle_max, obj->ops->type->handle_count );
  90. return grab_object( obj );
  91. }
  92. /* release an object and decrement its handle count */
  93. static void release_object_from_handle( struct object *obj )
  94. {
  95. assert( obj->handle_count );
  96. obj->ops->type->handle_count--;
  97. obj->handle_count--;
  98. release_object( obj );
  99. }
  100. static void handle_table_dump( struct object *obj, int verbose );
  101. static void handle_table_destroy( struct object *obj );
  102. static const struct object_ops handle_table_ops =
  103. {
  104. sizeof(struct handle_table), /* size */
  105. &no_type, /* type */
  106. handle_table_dump, /* dump */
  107. no_add_queue, /* add_queue */
  108. NULL, /* remove_queue */
  109. NULL, /* signaled */
  110. NULL, /* satisfied */
  111. no_signal, /* signal */
  112. no_get_fd, /* get_fd */
  113. default_map_access, /* map_access */
  114. default_get_sd, /* get_sd */
  115. default_set_sd, /* set_sd */
  116. no_get_full_name, /* get_full_name */
  117. no_lookup_name, /* lookup_name */
  118. no_link_name, /* link_name */
  119. NULL, /* unlink_name */
  120. no_open_file, /* open_file */
  121. no_kernel_obj_list, /* get_kernel_obj_list */
  122. no_close_handle, /* close_handle */
  123. handle_table_destroy /* destroy */
  124. };
  125. /* dump a handle table */
  126. static void handle_table_dump( struct object *obj, int verbose )
  127. {
  128. int i;
  129. struct handle_table *table = (struct handle_table *)obj;
  130. struct handle_entry *entry;
  131. assert( obj->ops == &handle_table_ops );
  132. fprintf( stderr, "Handle table last=%d count=%d process=%p\n",
  133. table->last, table->count, table->process );
  134. if (!verbose) return;
  135. entry = table->entries;
  136. for (i = 0; i <= table->last; i++, entry++)
  137. {
  138. if (!entry->ptr) continue;
  139. fprintf( stderr, " %04x: %p %08x ",
  140. index_to_handle(i), entry->ptr, entry->access );
  141. dump_object_name( entry->ptr );
  142. entry->ptr->ops->dump( entry->ptr, 0 );
  143. }
  144. }
  145. /* destroy a handle table */
  146. static void handle_table_destroy( struct object *obj )
  147. {
  148. int i;
  149. struct handle_table *table = (struct handle_table *)obj;
  150. struct handle_entry *entry;
  151. assert( obj->ops == &handle_table_ops );
  152. /* first notify all objects that handles are being closed */
  153. if (table->process)
  154. {
  155. for (i = 0, entry = table->entries; i <= table->last; i++, entry++)
  156. {
  157. struct object *obj = entry->ptr;
  158. if (obj) obj->ops->close_handle( obj, table->process, index_to_handle(i) );
  159. }
  160. }
  161. for (i = 0, entry = table->entries; i <= table->last; i++, entry++)
  162. {
  163. struct object *obj = entry->ptr;
  164. entry->ptr = NULL;
  165. if (obj) release_object_from_handle( obj );
  166. }
  167. free( table->entries );
  168. }
  169. /* close all the process handles and free the handle table */
  170. void close_process_handles( struct process *process )
  171. {
  172. struct handle_table *table = process->handles;
  173. process->handles = NULL;
  174. if (table) release_object( table );
  175. }
  176. /* allocate a new handle table */
  177. struct handle_table *alloc_handle_table( struct process *process, int count )
  178. {
  179. struct handle_table *table;
  180. if (count < MIN_HANDLE_ENTRIES) count = MIN_HANDLE_ENTRIES;
  181. if (!(table = alloc_object( &handle_table_ops )))
  182. return NULL;
  183. table->process = process;
  184. table->count = count;
  185. table->last = -1;
  186. table->free = 0;
  187. if ((table->entries = mem_alloc( count * sizeof(*table->entries) ))) return table;
  188. release_object( table );
  189. return NULL;
  190. }
  191. /* grow a handle table */
  192. static int grow_handle_table( struct handle_table *table )
  193. {
  194. struct handle_entry *new_entries;
  195. int count = min( table->count * 2, MAX_HANDLE_ENTRIES );
  196. if (count == table->count ||
  197. !(new_entries = realloc( table->entries, count * sizeof(struct handle_entry) )))
  198. {
  199. set_error( STATUS_INSUFFICIENT_RESOURCES );
  200. return 0;
  201. }
  202. table->entries = new_entries;
  203. table->count = count;
  204. return 1;
  205. }
  206. /* allocate the first free entry in the handle table */
  207. static obj_handle_t alloc_entry( struct handle_table *table, void *obj, unsigned int access )
  208. {
  209. struct handle_entry *entry = table->entries + table->free;
  210. int i;
  211. for (i = table->free; i <= table->last; i++, entry++) if (!entry->ptr) goto found;
  212. if (i >= table->count)
  213. {
  214. if (!grow_handle_table( table )) return 0;
  215. entry = table->entries + i; /* the entries may have moved */
  216. }
  217. table->last = i;
  218. found:
  219. table->free = i + 1;
  220. entry->ptr = grab_object_for_handle( obj );
  221. entry->access = access;
  222. return index_to_handle(i);
  223. }
  224. /* allocate a handle for an object, incrementing its refcount */
  225. static obj_handle_t alloc_handle_entry( struct process *process, void *ptr,
  226. unsigned int access, unsigned int attr )
  227. {
  228. struct object *obj = ptr;
  229. assert( !(access & RESERVED_ALL) );
  230. if (attr & OBJ_INHERIT) access |= RESERVED_INHERIT;
  231. if (!process->handles)
  232. {
  233. set_error( STATUS_PROCESS_IS_TERMINATING );
  234. return 0;
  235. }
  236. return alloc_entry( process->handles, obj, access );
  237. }
  238. /* allocate a handle for an object, incrementing its refcount */
  239. /* return the handle, or 0 on error */
  240. obj_handle_t alloc_handle_no_access_check( struct process *process, void *ptr, unsigned int access, unsigned int attr )
  241. {
  242. struct object *obj = ptr;
  243. if (access & MAXIMUM_ALLOWED) access = GENERIC_ALL;
  244. access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL;
  245. return alloc_handle_entry( process, ptr, access, attr );
  246. }
  247. /* allocate a handle for an object, checking the dacl allows the process to */
  248. /* access it and incrementing its refcount */
  249. /* return the handle, or 0 on error */
  250. obj_handle_t alloc_handle( struct process *process, void *ptr, unsigned int access, unsigned int attr )
  251. {
  252. struct object *obj = ptr;
  253. access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL;
  254. if (access && !check_object_access( NULL, obj, &access )) return 0;
  255. return alloc_handle_entry( process, ptr, access, attr );
  256. }
  257. /* allocate a global handle for an object, incrementing its refcount */
  258. /* return the handle, or 0 on error */
  259. static obj_handle_t alloc_global_handle_no_access_check( void *obj, unsigned int access )
  260. {
  261. if (!global_table)
  262. {
  263. if (!(global_table = alloc_handle_table( NULL, 0 )))
  264. return 0;
  265. make_object_permanent( &global_table->obj );
  266. }
  267. return handle_local_to_global( alloc_entry( global_table, obj, access ));
  268. }
  269. /* allocate a global handle for an object, checking the dacl allows the */
  270. /* process to access it and incrementing its refcount and incrementing its refcount */
  271. /* return the handle, or 0 on error */
  272. static obj_handle_t alloc_global_handle( void *obj, unsigned int access )
  273. {
  274. if (access && !check_object_access( NULL, obj, &access )) return 0;
  275. return alloc_global_handle_no_access_check( obj, access );
  276. }
  277. /* return a handle entry, or NULL if the handle is invalid */
  278. static struct handle_entry *get_handle( struct process *process, obj_handle_t handle )
  279. {
  280. struct handle_table *table = process->handles;
  281. struct handle_entry *entry;
  282. int index;
  283. if (handle_is_global(handle))
  284. {
  285. handle = handle_global_to_local(handle);
  286. table = global_table;
  287. }
  288. if (!table) return NULL;
  289. index = handle_to_index( handle );
  290. if (index < 0) return NULL;
  291. if (index > table->last) return NULL;
  292. entry = table->entries + index;
  293. if (!entry->ptr) return NULL;
  294. return entry;
  295. }
  296. /* attempt to shrink a table */
  297. static void shrink_handle_table( struct handle_table *table )
  298. {
  299. struct handle_entry *entry = table->entries + table->last;
  300. struct handle_entry *new_entries;
  301. int count = table->count;
  302. while (table->last >= 0)
  303. {
  304. if (entry->ptr) break;
  305. table->last--;
  306. entry--;
  307. }
  308. if (table->last >= count / 4) return; /* no need to shrink */
  309. if (count < MIN_HANDLE_ENTRIES * 2) return; /* too small to shrink */
  310. count /= 2;
  311. if (!(new_entries = realloc( table->entries, count * sizeof(*new_entries) ))) return;
  312. table->count = count;
  313. table->entries = new_entries;
  314. }
  315. static void inherit_handle( struct process *parent, const obj_handle_t handle, struct handle_table *table )
  316. {
  317. struct handle_entry *dst, *src;
  318. int index;
  319. dst = table->entries;
  320. src = get_handle( parent, handle );
  321. if (!src || !(src->access & RESERVED_INHERIT)) return;
  322. index = handle_to_index( handle );
  323. if (dst[index].ptr) return;
  324. grab_object_for_handle( src->ptr );
  325. dst[index] = *src;
  326. table->last = max( table->last, index );
  327. }
  328. /* copy the handle table of the parent process */
  329. /* return 1 if OK, 0 on error */
  330. struct handle_table *copy_handle_table( struct process *process, struct process *parent,
  331. const obj_handle_t *handles, unsigned int handle_count,
  332. const obj_handle_t *std_handles )
  333. {
  334. struct handle_table *parent_table = parent->handles;
  335. struct handle_table *table;
  336. int i;
  337. assert( parent_table );
  338. assert( parent_table->obj.ops == &handle_table_ops );
  339. if (!(table = alloc_handle_table( process, parent_table->count )))
  340. return NULL;
  341. if (handles)
  342. {
  343. memset( table->entries, 0, parent_table->count * sizeof(*table->entries) );
  344. for (i = 0; i < handle_count; i++)
  345. {
  346. inherit_handle( parent, handles[i], table );
  347. }
  348. for (i = 0; i < 3; i++)
  349. {
  350. inherit_handle( parent, std_handles[i], table );
  351. }
  352. }
  353. else
  354. {
  355. if ((table->last = parent_table->last) >= 0)
  356. {
  357. struct handle_entry *ptr = table->entries;
  358. memcpy( ptr, parent_table->entries, (table->last + 1) * sizeof(struct handle_entry) );
  359. for (i = 0; i <= table->last; i++, ptr++)
  360. {
  361. if (!ptr->ptr) continue;
  362. if (ptr->access & RESERVED_INHERIT) grab_object_for_handle( ptr->ptr );
  363. else ptr->ptr = NULL; /* don't inherit this entry */
  364. }
  365. }
  366. }
  367. /* attempt to shrink the table */
  368. shrink_handle_table( table );
  369. return table;
  370. }
  371. /* close a handle and decrement the refcount of the associated object */
  372. unsigned int close_handle( struct process *process, obj_handle_t handle )
  373. {
  374. struct handle_table *table;
  375. struct handle_entry *entry;
  376. struct object *obj;
  377. if (!(entry = get_handle( process, handle ))) return STATUS_INVALID_HANDLE;
  378. if (entry->access & RESERVED_CLOSE_PROTECT) return STATUS_HANDLE_NOT_CLOSABLE;
  379. obj = entry->ptr;
  380. if (!obj->ops->close_handle( obj, process, handle )) return STATUS_HANDLE_NOT_CLOSABLE;
  381. entry->ptr = NULL;
  382. table = handle_is_global(handle) ? global_table : process->handles;
  383. if (entry < table->entries + table->free) table->free = entry - table->entries;
  384. if (entry == table->entries + table->last) shrink_handle_table( table );
  385. release_object_from_handle( obj );
  386. return STATUS_SUCCESS;
  387. }
  388. /* retrieve the object corresponding to one of the magic pseudo-handles */
  389. static inline struct object *get_magic_handle( obj_handle_t handle )
  390. {
  391. switch(handle)
  392. {
  393. case 0xfffffffa: /* current thread impersonation token pseudo-handle */
  394. return (struct object *)thread_get_impersonation_token( current );
  395. case 0xfffffffb: /* current thread token pseudo-handle */
  396. return (struct object *)current->token;
  397. case 0xfffffffc: /* current process token pseudo-handle */
  398. return (struct object *)current->process->token;
  399. case 0xfffffffe: /* current thread pseudo-handle */
  400. return &current->obj;
  401. case 0x7fffffff: /* current process pseudo-handle */
  402. case 0xffffffff: /* current process pseudo-handle */
  403. return (struct object *)current->process;
  404. default:
  405. return NULL;
  406. }
  407. }
  408. /* retrieve the object corresponding to a handle, incrementing its refcount */
  409. struct object *get_handle_obj( struct process *process, obj_handle_t handle,
  410. unsigned int access, const struct object_ops *ops )
  411. {
  412. struct handle_entry *entry;
  413. struct object *obj;
  414. if (!(obj = get_magic_handle( handle )))
  415. {
  416. if (!(entry = get_handle( process, handle )))
  417. {
  418. set_error( STATUS_INVALID_HANDLE );
  419. return NULL;
  420. }
  421. obj = entry->ptr;
  422. if (ops && (obj->ops != ops))
  423. {
  424. set_error( STATUS_OBJECT_TYPE_MISMATCH ); /* not the right type */
  425. return NULL;
  426. }
  427. if ((entry->access & access) != access)
  428. {
  429. set_error( STATUS_ACCESS_DENIED );
  430. return NULL;
  431. }
  432. }
  433. else if (ops && (obj->ops != ops))
  434. {
  435. set_error( STATUS_OBJECT_TYPE_MISMATCH ); /* not the right type */
  436. return NULL;
  437. }
  438. return grab_object( obj );
  439. }
  440. /* retrieve the access rights of a given handle */
  441. unsigned int get_handle_access( struct process *process, obj_handle_t handle )
  442. {
  443. struct handle_entry *entry;
  444. if (get_magic_handle( handle )) return ~RESERVED_ALL; /* magic handles have all access rights */
  445. if (!(entry = get_handle( process, handle ))) return 0;
  446. return entry->access & ~RESERVED_ALL;
  447. }
  448. /* find the first inherited handle of the given type */
  449. /* this is needed for window stations and desktops (don't ask...) */
  450. obj_handle_t find_inherited_handle( struct process *process, const struct object_ops *ops )
  451. {
  452. struct handle_table *table = process->handles;
  453. struct handle_entry *ptr;
  454. int i;
  455. if (!table) return 0;
  456. for (i = 0, ptr = table->entries; i <= table->last; i++, ptr++)
  457. {
  458. if (!ptr->ptr) continue;
  459. if (ptr->ptr->ops != ops) continue;
  460. if (ptr->access & RESERVED_INHERIT) return index_to_handle(i);
  461. }
  462. return 0;
  463. }
  464. /* get/set the handle reserved flags */
  465. /* return the old flags (or -1 on error) */
  466. static int set_handle_flags( struct process *process, obj_handle_t handle, int mask, int flags )
  467. {
  468. struct handle_entry *entry;
  469. unsigned int old_access;
  470. if (get_magic_handle( handle ))
  471. {
  472. /* we can retrieve but not set info for magic handles */
  473. if (mask) set_error( STATUS_ACCESS_DENIED );
  474. return 0;
  475. }
  476. if (!(entry = get_handle( process, handle )))
  477. {
  478. set_error( STATUS_INVALID_HANDLE );
  479. return -1;
  480. }
  481. old_access = entry->access;
  482. mask = (mask << RESERVED_SHIFT) & RESERVED_ALL;
  483. flags = (flags << RESERVED_SHIFT) & mask;
  484. entry->access = (entry->access & ~mask) | flags;
  485. return (old_access & RESERVED_ALL) >> RESERVED_SHIFT;
  486. }
  487. /* duplicate a handle */
  488. obj_handle_t duplicate_handle( struct process *src, obj_handle_t src_handle, struct process *dst,
  489. unsigned int access, unsigned int attr, unsigned int options )
  490. {
  491. obj_handle_t res;
  492. struct handle_entry *entry;
  493. unsigned int src_access;
  494. struct object *obj = get_handle_obj( src, src_handle, 0, NULL );
  495. if (!obj) return 0;
  496. if ((entry = get_handle( src, src_handle )))
  497. src_access = entry->access;
  498. else /* pseudo-handle, give it full access */
  499. src_access = obj->ops->map_access( obj, GENERIC_ALL );
  500. src_access &= ~RESERVED_ALL;
  501. if (options & DUPLICATE_SAME_ACCESS)
  502. access = src_access;
  503. else
  504. access = obj->ops->map_access( obj, access ) & ~RESERVED_ALL;
  505. /* asking for the more access rights than src_access? */
  506. if (access & ~src_access)
  507. {
  508. if ((current->token && !check_object_access( current->token, obj, &access )) ||
  509. !check_object_access( dst->token, obj, &access ))
  510. {
  511. release_object( obj );
  512. return 0;
  513. }
  514. if (options & DUPLICATE_MAKE_GLOBAL)
  515. res = alloc_global_handle( obj, access );
  516. else
  517. res = alloc_handle_no_access_check( dst, obj, access, attr );
  518. }
  519. else
  520. {
  521. if (options & DUPLICATE_MAKE_GLOBAL)
  522. res = alloc_global_handle_no_access_check( obj, access );
  523. else if ((options & DUPLICATE_CLOSE_SOURCE) && src == dst &&
  524. entry && !(entry->access & RESERVED_CLOSE_PROTECT))
  525. {
  526. if (attr & OBJ_INHERIT) access |= RESERVED_INHERIT;
  527. entry->access = access;
  528. res = src_handle;
  529. }
  530. else
  531. res = alloc_handle_entry( dst, obj, access, attr );
  532. }
  533. release_object( obj );
  534. return res;
  535. }
  536. /* open a new handle to an existing object */
  537. obj_handle_t open_object( struct process *process, obj_handle_t parent, unsigned int access,
  538. const struct object_ops *ops, const struct unicode_str *name,
  539. unsigned int attributes )
  540. {
  541. obj_handle_t handle = 0;
  542. struct object *obj, *root = NULL;
  543. if (name->len >= 65534)
  544. {
  545. set_error( STATUS_OBJECT_NAME_INVALID );
  546. return 0;
  547. }
  548. if (parent)
  549. {
  550. if (name->len)
  551. root = get_directory_obj( process, parent );
  552. else /* opening the object itself can work for non-directories too */
  553. root = get_handle_obj( process, parent, 0, NULL );
  554. if (!root) return 0;
  555. }
  556. if ((obj = open_named_object( root, ops, name, attributes )))
  557. {
  558. handle = alloc_handle( process, obj, access, attributes );
  559. release_object( obj );
  560. }
  561. if (root) release_object( root );
  562. return handle;
  563. }
  564. /* return the size of the handle table of a given process */
  565. unsigned int get_handle_table_count( struct process *process )
  566. {
  567. if (!process->handles) return 0;
  568. return process->handles->count;
  569. }
  570. /* close a handle */
  571. DECL_HANDLER(close_handle)
  572. {
  573. unsigned int err = close_handle( current->process, req->handle );
  574. set_error( err );
  575. }
  576. /* set a handle information */
  577. DECL_HANDLER(set_handle_info)
  578. {
  579. reply->old_flags = set_handle_flags( current->process, req->handle, req->mask, req->flags );
  580. }
  581. /* duplicate a handle */
  582. DECL_HANDLER(dup_handle)
  583. {
  584. struct process *src, *dst = NULL;
  585. reply->handle = 0;
  586. if ((src = get_process_from_handle( req->src_process, PROCESS_DUP_HANDLE )))
  587. {
  588. if (req->options & DUPLICATE_MAKE_GLOBAL)
  589. {
  590. reply->handle = duplicate_handle( src, req->src_handle, NULL,
  591. req->access, req->attributes, req->options );
  592. }
  593. else if ((dst = get_process_from_handle( req->dst_process, PROCESS_DUP_HANDLE )))
  594. {
  595. reply->handle = duplicate_handle( src, req->src_handle, dst,
  596. req->access, req->attributes, req->options );
  597. release_object( dst );
  598. }
  599. /* close the handle no matter what happened */
  600. if ((req->options & DUPLICATE_CLOSE_SOURCE) && (src != dst || req->src_handle != reply->handle))
  601. close_handle( src, req->src_handle );
  602. release_object( src );
  603. }
  604. }
  605. DECL_HANDLER(get_object_info)
  606. {
  607. struct object *obj;
  608. WCHAR *name;
  609. if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
  610. reply->access = get_handle_access( current->process, req->handle );
  611. reply->ref_count = obj->refcount;
  612. reply->handle_count = obj->handle_count;
  613. if ((name = obj->ops->get_full_name( obj, &reply->total )))
  614. set_reply_data_ptr( name, min( reply->total, get_reply_max_size() ));
  615. release_object( obj );
  616. }
  617. DECL_HANDLER(set_security_object)
  618. {
  619. data_size_t sd_size = get_req_data_size();
  620. const struct security_descriptor *sd = get_req_data();
  621. struct object *obj;
  622. unsigned int access = 0;
  623. if (!sd_is_valid( sd, sd_size ))
  624. {
  625. set_error( STATUS_ACCESS_VIOLATION );
  626. return;
  627. }
  628. if (req->security_info & OWNER_SECURITY_INFORMATION ||
  629. req->security_info & GROUP_SECURITY_INFORMATION ||
  630. req->security_info & LABEL_SECURITY_INFORMATION)
  631. access |= WRITE_OWNER;
  632. if (req->security_info & SACL_SECURITY_INFORMATION)
  633. access |= ACCESS_SYSTEM_SECURITY;
  634. if (req->security_info & DACL_SECURITY_INFORMATION)
  635. access |= WRITE_DAC;
  636. if (!(obj = get_handle_obj( current->process, req->handle, access, NULL ))) return;
  637. obj->ops->set_sd( obj, sd, req->security_info );
  638. release_object( obj );
  639. }
  640. DECL_HANDLER(get_security_object)
  641. {
  642. const struct security_descriptor *sd;
  643. struct object *obj;
  644. unsigned int access = READ_CONTROL;
  645. struct security_descriptor req_sd;
  646. int present;
  647. const SID *owner, *group;
  648. const ACL *sacl, *dacl;
  649. ACL *label_acl = NULL;
  650. if (req->security_info & SACL_SECURITY_INFORMATION)
  651. access |= ACCESS_SYSTEM_SECURITY;
  652. if (!(obj = get_handle_obj( current->process, req->handle, access, NULL ))) return;
  653. sd = obj->ops->get_sd( obj );
  654. if (sd)
  655. {
  656. req_sd.control = sd->control & ~SE_SELF_RELATIVE;
  657. owner = sd_get_owner( sd );
  658. if (req->security_info & OWNER_SECURITY_INFORMATION)
  659. req_sd.owner_len = sd->owner_len;
  660. else
  661. req_sd.owner_len = 0;
  662. group = sd_get_group( sd );
  663. if (req->security_info & GROUP_SECURITY_INFORMATION)
  664. req_sd.group_len = sd->group_len;
  665. else
  666. req_sd.group_len = 0;
  667. sacl = sd_get_sacl( sd, &present );
  668. if (req->security_info & SACL_SECURITY_INFORMATION && present)
  669. req_sd.sacl_len = sd->sacl_len;
  670. else if (req->security_info & LABEL_SECURITY_INFORMATION && present && sacl)
  671. {
  672. if (!(label_acl = extract_security_labels( sacl ))) goto done;
  673. req_sd.sacl_len = label_acl->AclSize;
  674. sacl = label_acl;
  675. }
  676. else
  677. req_sd.sacl_len = 0;
  678. dacl = sd_get_dacl( sd, &present );
  679. if (req->security_info & DACL_SECURITY_INFORMATION && present)
  680. req_sd.dacl_len = sd->dacl_len;
  681. else
  682. req_sd.dacl_len = 0;
  683. reply->sd_len = sizeof(req_sd) + req_sd.owner_len + req_sd.group_len +
  684. req_sd.sacl_len + req_sd.dacl_len;
  685. if (reply->sd_len <= get_reply_max_size())
  686. {
  687. char *ptr = set_reply_data_size(reply->sd_len);
  688. memcpy( ptr, &req_sd, sizeof(req_sd) );
  689. ptr += sizeof(req_sd);
  690. memcpy( ptr, owner, req_sd.owner_len );
  691. ptr += req_sd.owner_len;
  692. memcpy( ptr, group, req_sd.group_len );
  693. ptr += req_sd.group_len;
  694. memcpy( ptr, sacl, req_sd.sacl_len );
  695. ptr += req_sd.sacl_len;
  696. memcpy( ptr, dacl, req_sd.dacl_len );
  697. }
  698. else
  699. set_error(STATUS_BUFFER_TOO_SMALL);
  700. }
  701. done:
  702. release_object( obj );
  703. free( label_acl );
  704. }
  705. struct enum_handle_info
  706. {
  707. unsigned int count;
  708. struct handle_info *handle;
  709. };
  710. static int enum_handles( struct process *process, void *user )
  711. {
  712. struct enum_handle_info *info = user;
  713. struct handle_table *table = process->handles;
  714. struct handle_entry *entry;
  715. struct handle_info *handle;
  716. unsigned int i;
  717. if (!table)
  718. return 0;
  719. for (i = 0, entry = table->entries; i <= table->last; i++, entry++)
  720. {
  721. if (!entry->ptr) continue;
  722. if (!info->handle)
  723. {
  724. info->count++;
  725. continue;
  726. }
  727. assert( info->count );
  728. handle = info->handle++;
  729. handle->owner = process->id;
  730. handle->handle = index_to_handle(i);
  731. handle->access = entry->access & ~RESERVED_ALL;
  732. handle->type = entry->ptr->ops->type->index;
  733. handle->attributes = 0;
  734. if (entry->access & RESERVED_INHERIT) handle->attributes |= OBJ_INHERIT;
  735. if (entry->access & RESERVED_CLOSE_PROTECT) handle->attributes |= OBJ_PROTECT_CLOSE;
  736. info->count--;
  737. }
  738. return 0;
  739. }
  740. DECL_HANDLER(get_system_handles)
  741. {
  742. struct enum_handle_info info;
  743. struct handle_info *handle;
  744. data_size_t max_handles = get_reply_max_size() / sizeof(*handle);
  745. info.handle = NULL;
  746. info.count = 0;
  747. enum_processes( enum_handles, &info );
  748. reply->count = info.count;
  749. if (max_handles < info.count)
  750. set_error( STATUS_BUFFER_TOO_SMALL );
  751. else if ((handle = set_reply_data_size( info.count * sizeof(*handle) )))
  752. {
  753. info.handle = handle;
  754. enum_processes( enum_handles, &info );
  755. }
  756. }
  757. DECL_HANDLER(make_temporary)
  758. {
  759. struct object *obj;
  760. if (!(obj = get_handle_obj( current->process, req->handle, 0, NULL ))) return;
  761. if (obj->is_permanent)
  762. {
  763. make_object_temporary( obj );
  764. release_object( obj );
  765. }
  766. release_object( obj );
  767. }