📄 object.c
字号:
/* * object.c * * Authors: * - Chenzhan Hu, Lixing Chu, Limin Jin, Liwei Zhou, Zhiqiang Jiao * * This software has been developed while working on the Linux Unified Kernel * project (http://linux.insigma.com.cn) in the Insigma Reaserch Institute, * which is a subdivision of Insigma Co., Ltd (http://www.insigma.com.cn). * * The project is sponsored by Insigma Co., Ltd. * * The authors can be reached at linux@insigma.com.cn. * * This program is free software; you can redistribute it and/or modify it * under the terms of the GNU General Public License as published by the * Free Software Foundation; either version 2 of the License, or (at your * option) any later version. * * Revision History: * Jan 2006 - Modified. */ /* * object.c:win32 object handling * Reference to Kernel-win32 code */#include <linux/module.h>#include <linux/win32_process.h>#include <linux/mm.h>#include <asm/uaccess.h>#include "win32.h"#ifdef CONFIG_UNIFIED_KERNELextern struct list_head object_class_list;extern spinlock_t object_list_lock;extern int unistr2charstr(PWSTR,LPCSTR);extern wchar_t *getwname(const wchar_t *);extern void putwname(const wchar_t *);/* * fetch an object name into kernelspace, * and object name will be convert into char string */int fetch_oname(struct oname *oname, const char *name){ PWSTR uniname; int ret; /* anonymous */ if (!name) { oname->name = NULL; oname->nhash = 0; return 0; } /* retrieve the name */ uniname = getwname((PWSTR) name); oname->name = __getname(); if (IS_ERR(oname->name)) { ret = PTR_ERR(oname->name); goto clean_up; } if((ret = unistr2charstr(uniname,oname->name)) < 0) goto clean_up; oname->nhash = full_name_hash(oname->name,strlen(oname->name)); ret = 0;clean_up: putwname(uniname); return ret;} /* end fetch_oname() *//* * initialise the system bits of the object class */void InitObjectClass(struct win32_object_class *clss){ int i; rwlock_init(&clss->oc_lock); for (i=0; i<OBJCLASSNOBJSSIZE; i++) INIT_LIST_HEAD(&clss->oc_nobjs[i]); INIT_LIST_HEAD(&clss->oc_aobjs); list_add(&clss->oc_next,&object_class_list);} /* end InitObjectClass() *//* * find an already extant internal object record * - call with object class lock held * - name must be in kernelspace * - leaves object usage incremented * - check the result with IS_ERR() */static win32_object *__FindObject(struct win32_object_class *clss, const struct oname *name){ struct list_head *olist; win32_object *obj; /* can't find an anonymous object by name */ if (!name->name) return ERR_PTR(-ENOENT); /* search the object class */ list_for_each(olist,&clss->oc_nobjs[name->nhash&OBJCLASSNOBJSMASK]) { obj = (win32_object*) olist; if (obj->o_name.nhash==name->nhash && strcmp(obj->o_name.name,name->name)==0 ) goto found_object; } return ERR_PTR(-ENOENT);found_object: objget(obj); return obj;} /* end __FindObject() *//* * find an already extant internal object record * - name must be in userspace * - leaves object usage incremented * - check the result with IS_ERR() */win32_object *FindObject(struct win32_object_class *clss, const char *name){ struct oname oname; win32_object *obj; int err; /* retrieve the name */ err = fetch_oname(&oname,name); if (err<0) return ERR_PTR(err); /* allocate an object */ read_lock(&clss->oc_lock); obj = __FindObject(clss,&oname); read_unlock(&clss->oc_lock); if (oname.name) putname(oname.name); return obj;} /* end FindObject() *//* * allocate and initialise an internal object record * - name buffer may be stolen from caller (in which case name->name set to 0) * - leaves object usage incremented * - check the result with IS_ERR() * - data is passed to the object class (re)constructor function */static win32_object *_AllocObject(struct win32_object_class *clss, struct oname *name, void *data){ win32_object *obj; int err; /* need to do the whole thing inside of the class lock, since Win32 * object-create will open an object of the same name if one exists, * and create one if not; but there must be no gap between the search * and creation or else two separate processes can create objects of * the same name */ write_lock(&clss->oc_lock); /* see if the object already exists */ obj = __FindObject(clss,name); if (obj!=ERR_PTR(-ENOENT)) { if (IS_ERR(obj)) goto cleanup_1; /* call the object reconstructor without the class lock held * (since it may wait and since we aren't actually modifying * the object class anyway) */ write_unlock(&clss->oc_lock); if (clss->reconstructor) { err = clss->reconstructor(obj,data); if (err<0) { objput(obj); obj = ERR_PTR(err); } } goto cleanup_0; } /* create and initialise an object */ err = -ENOMEM; obj = (win32_object *) kmalloc(sizeof(win32_object),GFP_KERNEL); if (!obj) goto cleanup_2; memset(obj,0,sizeof(win32_object)); atomic_set(&obj->o_count,1); init_waitqueue_head(&obj->o_wait);#ifdef OBJECT_MAGIC obj->o_magic = OBJECT_MAGIC;#endif /* name anonymous objects as "class:objaddr" if so requested */ if (!name->name && ~clss->oc_flags&OCF_DONT_NAME_ANON) { err = -ENOMEM; obj->o_name.name = __getname(); if (!obj->o_name.name) goto cleanup_3; sprintf(obj->o_name.name,"%s:%p",clss->oc_type,obj); obj->o_name.nhash = full_name_hash(obj->o_name.name, strlen(obj->o_name.name)); } /* cut'n'paste the name from the caller's name buffer */ else { obj->o_name.name = name->name; obj->o_name.nhash = name->nhash; name->name = NULL; } /* attach to appropriate object class list */ obj->o_class = clss; if (obj->o_name.name) list_add(&obj->o_objlist, &clss->oc_nobjs[obj->o_name.nhash&OBJCLASSNOBJSMASK]); else list_add(&obj->o_objlist,&clss->oc_aobjs); err = clss->constructor(obj,data); /* call the object constructor */ if (err==0) goto cleanup_1; list_del(&obj->o_objlist);cleanup_3: if (obj->o_name.name) putname(obj->o_name.name); kfree(obj);cleanup_2: obj = ERR_PTR(err);cleanup_1: write_unlock(&clss->oc_lock);cleanup_0: return obj;} /* end _AllocObject() *//* * allocate an object with the specified name (may be NULL for anonymous) */win32_object *AllocObject(struct win32_object_class *clss, const char *name, void *data){ struct oname oname; win32_object *obj; int err; /* retrieve the name */ err = fetch_oname(&oname,name); if (err<0) return ERR_PTR(err); /* allocate an object */ obj = _AllocObject(clss,&oname,data); if (oname.name) putname(oname.name); return obj;} /* end AllocObject() *//* * create an object and attach it to a process handle * - pulls name into a kmalloc'd buffer * - leaves object usage incremented * - check the result with IS_ERR() * - handle returned in *hObject */win32_object *CreateObject(struct ethread *thread, struct win32_object_class *clss, const char *name, void *data, HANDLE *hObject ){ struct eprocess *process; struct oname oname; win32_object *obj, **ppobj, **epobj; int err; *hObject = NULL; /* retrieve the name */ err = fetch_oname(&oname,name); if (err<0) return ERR_PTR(err); /* allocate an object */ obj = _AllocObject(clss,&oname,data); if (oname.name) putname(oname.name); if (IS_ERR(obj)) return obj; /* find a handle slot */ process = get_eprocess(thread); epobj = &process->ep_handles[MAXHANDLES]; write_lock(&process->ep_lock); for (ppobj=process->ep_handles; ppobj<epobj; ppobj++) { if (!*ppobj) goto found_handle; } write_unlock(&process->ep_lock); objput(obj); return ERR_PTR(-EMFILE);found_handle: /* make link to object */ objget(obj); *ppobj = obj; write_unlock(&process->ep_lock); ppobj++; /* don't use the NULL handle */ *hObject = (HANDLE) ((char*)ppobj - (char*)process->ep_handles); return obj;} /* end CreateObject() *//* * search for an object by name, and attach to it if in existence * - leaves object usage incremented * - check the result with IS_ERR() * - handle returned in Win32serverIoctl structure */win32_object *OpenObject(struct ethread *thread, struct win32_object_class *clss, const char *name, HANDLE *hObject ){ struct eprocess *process; struct oname oname; win32_object *obj, **ppobj, **epobj; int err; *hObject = NULL; /* retrieve the name */ err = fetch_oname(&oname,name); if (err<0) return ERR_PTR(err); /* allocate an object */ read_lock(&clss->oc_lock); obj = __FindObject(clss,&oname); read_unlock(&clss->oc_lock); if (oname.name) putname(oname.name); if (IS_ERR(obj)) return obj; /* find a handle slot */ process = get_eprocess(thread); epobj = &process->ep_handles[MAXHANDLES]; write_lock(&process->ep_lock); for (ppobj=process->ep_handles; ppobj<epobj; ppobj++) if (!*ppobj) goto found_handle; write_unlock(&process->ep_lock); objput(obj); return ERR_PTR(-EMFILE);found_handle: /* make link to object */ objget(obj); *ppobj = obj; write_unlock(&process->ep_lock); ppobj++; /* don't use the NULL handle */ *hObject = (HANDLE) ((char*)ppobj - (char*)process->ep_handles); return obj;} /* end OpenObject() *//* * find the object associated with a handle * - leaves object usage incremented * - check the result with IS_ERR() */win32_object *GetObject(struct ethread *thread, HANDLE handle, struct win32_object_class *clss){ struct eprocess *process; win32_object *obj; /* validate the handle */ if (handle<MINHANDLE || handle>=MAXHANDLE || ((__u32)handle & (sizeof(win32_object*)-1)) ) return ERR_PTR(-EINVAL); process = get_eprocess(thread); read_lock(&process->ep_lock); obj = *(win32_object**) ((char*)process->ep_handles + (int)handle - sizeof(win32_object*) ); if (!obj) goto out; if (clss && obj->o_class!=clss) goto bad_object_type; objget(obj); read_unlock(&process->ep_lock);out: return obj ? obj : ERR_PTR(-EBADF); /* trying to do operation not available on this object type */bad_object_type: read_unlock(&process->ep_lock); return ERR_PTR(-EIO);} /* end GetObject() *//* * decrement an object's usage count * - when usage count reaches zero, the object is destroyed * - uses the class's rwlock to govern access to the count */void objput(win32_object *obj){ if (!obj) return;#ifdef OBJECT_MAGIC if (obj->o_magic!=OBJECT_MAGIC) panic("bad object magic\n");#endif write_lock(&obj->o_class->oc_lock); if (!atomic_dec_and_test(&obj->o_count)) goto still_in_use;#ifdef OBJECT_MAGIC obj->o_magic = 0x01010101;#endif list_del(&obj->o_objlist); obj->o_class->destructor(obj); write_unlock(&obj->o_class->oc_lock); /* quick insanity check */ if (waitqueue_active(&obj->o_wait)) { kdebug(KERN_ALERT "win32:" " object being deleted is still being waited upon\n"); return; } if (obj->o_name.name) putname(obj->o_name.name); kfree(obj); return;still_in_use: write_unlock(&obj->o_class->oc_lock);} /* end objput() */#endif
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -