Example #1
0
/**
 * Destroys thread local variables, sets exit event and dereferences
 * the thread handle.
 */
STATIC void THREAD_Cleanup(ThrData* thr)
{
    /* invoke destructors for thread local variables */
    int i, n = 1;
    for (i=0; i<MAX_DESTRUCTOR_ITERATIONS && n > 0; i++) {
        int k;
        n = 0;
        for (k=0; k<VECTOR_Size(&thr->cleanupList); k++) {
            ThrKey key = VECTOR_Get(&thr->cleanupList, k);
            void * value = TlsGetValue(key->index);
            if (value) {
                TlsSetValue(key->index, NULL);
#ifdef _USE_EXCEPTION_HANDLING
                __try {
#endif /* _USE_EXCEPTION_HANDLING */

                    key->clean(value);
                    ASSERT(!TlsGetValue(key->index));

#ifdef _USE_EXCEPTION_HANDLING
                } __except(EXCEPTION_EXECUTE_HANDLER) {
                    TlsSetValue(key->index,NULL);
                    ASSMSG1("EXCEPTION %08lX in cleanup proc!",
                            GetExceptionCode());
                }
#endif /* _USE_EXCEPTION_HANDLING */
                n++;
            }
        }
    }

    ASSERT(i<MAX_DESTRUCTOR_ITERATIONS);

    /* Dereference ThrKey structures */
    while ((n = VECTOR_Size(&thr->cleanupList)) > 0) {
        ThrKey key = VECTOR_Remove(&thr->cleanupList, n-1);
        if (InterlockedDecrement(&key->ref) == 0) {
            ASSERT(key->index == TLS_OUT_OF_INDEXES);
            MEM_Free(key);
        }
    }

    InterlockedDecrement(&WIN32_ThreadCount);
    VECTOR_Destroy(&thr->cleanupList);
    EVENT_Set(&thr->exitEvent);
    THREAD_Deref(thr);
}
Example #2
0
STATIC void EXPAT_StartElement(void * ctx, XML_Str tag, XML_Str * atts)
{
    ExpatContext * expat = (ExpatContext *)ctx;
    if (expat->cb.startElem) {
        XMLAttr aset;
        XML_Str * s = atts;

        BUFFER_Clear(&expat->buf);
        VECTOR_Clear(&expat->atts);
        while (*s) {
            Char tmp;
            const XML_Char * c = (*s);

            /* 
             * store offset in the vector - later will be replaces with the 
             * pointer. Cannot store the pointers now because buffer may be
             * reallocated during conversion. 
             */
            int off = BUFFER_Size(&expat->buf)/sizeof(Char);
            VECTOR_Add(&expat->atts,(VElement)(PtrWord)off);
            
            /*
             * Pretty naive convertion of attribute names and values from
             * XML_Str to Str. This part may need some improvement...
             */
            while (*c) {
                tmp = (Char)*c;
                BUFFER_Put(&expat->buf, &tmp, sizeof(tmp), False);
                c++;
            }
            tmp = 0;
            BUFFER_Put(&expat->buf, &tmp, sizeof(tmp), False);
            s++;
        }

        ASSERT(!(VECTOR_Size(&expat->atts)%2));
        aset.storage = (Char*)BUFFER_Access(&expat->buf);
        aset.size = BUFFER_Size(&expat->buf);
        aset.off = (int*)VECTOR_GetElements(&expat->atts);
        aset.n = VECTOR_Size(&expat->atts)/2;

        EXPAT_ConvertTag(&expat->sb, tag);
        (*expat->cb.startElem)(expat->ctx, STRBUF_Text(&expat->sb), &aset);
    }
}
Example #3
0
/*
 * XML_Handle parses well-formed XML stream returning the root tag context
 * on success, NULL on failure. The endTag callback provided by the root tag
 * handler can be used to deallocate the root tag can context without any
 * side effects. However, in order to extract any useful information from the 
 * root tag context, each object providing root tag handler would normally
 * provide a function that would exract such information from the root tag 
 * (and deallocate everything else).
 *
 * The last parameter is a context parameter passed to the root tag callback
 * as the first argument. The code calling XML_Handle or the XMLHandleRoot
 * callback directly must know that XMLHandleRoot expects as a context
 * parameter. Typically, this is not a problem, but the use of this parameter
 * is discouraged. The XML stream should be self-sufficient, i.e. it should
 * contain all the information necessary to completely parse it. The context
 * parameter exists primarily to support for legacy XML file formats that 
 * require extra parsing information in addition to the information contained
 * in the XML stream itself.
 */
XMLTag * XML_Handle(File * f, Str tag, XMLHandleRoot root, void * ctx)
{
    XMLTag * rootTag = NULL;
    XMLContext context;
    memset(&context, 0, sizeof(context));
    context.rootTagName = tag;
    context.rootHandler = root;
    context.rootContext = ctx;
    if (VECTOR_Init(&context.stack, 0, NULL, XML_VectorFreeTagContext)) {
        XMLCallbacks cb;
        memset(&cb, 0, sizeof(cb));
        cb.startElem = XML_HandleStartElem;
        cb.endElem = XML_HandleEndElem;
        cb.charData = XML_HandleCharData;
        if (!XML_ParseStream(f, &cb, &context)) {
            context.error = True;
        }
        if (!context.error) {
            rootTag = context.rootTag;
        } else if (context.rootTag) {
            if (context.rootTag->endTag) {
                context.rootTag->endTag(context.rootTag, NULL);
            } else {
                MEM_Free(context.rootTag);
            }
        }

        /* 
         * VECTOR_Destroy would destroy the elements starting with the
         * first element. We must start with the last element, which is
         * a natural cleanup order for a stack. If parsing was successful,
         * the vector is already empty. However, if parsing failed, the
         * vector may be non-empty and the order in which we deallocate the
         * tags must be opposite to the order in which they were created.
         */
        while (!VECTOR_IsEmpty(&context.stack)) {
            VECTOR_Remove(&context.stack, VECTOR_Size(&context.stack)-1);
        }
        VECTOR_Destroy(&context.stack);
    }
    return rootTag;
}
Example #4
0
/**
 * Character handler for XML_Handle. Passes the data to the current
 * element handler.
 */
STATIC void XML_HandleCharData(void * ctx, const wchar_t * s, int len)
{
    XMLContext * context = (XMLContext*)ctx;
    int depth = VECTOR_Size(&context->stack);
    ASSERT(depth > 0);
    if (depth > 0 && !context->error) {
        XMLTagCtx * tagContext;
        tagContext = (XMLTagCtx*)VECTOR_Get(&context->stack,depth-1);
        ASSERT(tagContext && tagContext->context == context);

        /* 
         * if the handler does not expect any character data, we ignore those
         * characters, although it might be considered an error...
         */
        if (tagContext->tag->handleChars) {
            if (!tagContext->tag->handleChars(tagContext->tag, s, len)) {
                context->error = True;
            }
        }
    }
}
Example #5
0
/**
 * "End element" callback for XML_Handle. If this tag has been "skipped" by
 * XML_StartElemCB, simply decrements skipDepth. Otherwise, calls the client
 * callback to deallocate the tag context.
 */
STATIC void XML_HandleEndElem(void * ctx, Str tag)
{
    XMLContext * context = (XMLContext*)ctx;
    UNREF(tag);
    if (context->error && context->skipDepth > 0) {
        context->skipDepth--;
    } else {    
        int depth = VECTOR_Size(&context->stack);
        ASSERT(depth > 0);
        if (depth == 1 && !context->error) {
            XMLTagCtx * root;
            root = (XMLTagCtx*)VECTOR_Get(&context->stack,0);
            ASSERT(root && root->context == context);
            ASSERT(!context->rootTag);

            /* prevent XML_VectorFreeTagContext from deallocating the tag */
            context->rootTag = root->tag;
            root->tag = NULL;
        }
        if (depth > 0) {
            VECTOR_Remove(&context->stack, depth-1);
        }
    }
}
Example #6
0
/**
 * This does essentially the same as JVM_Find2, only additional directories
 * are passed in as a variable list of strings. The list of directories
 * must be NULL terminated, for example:
 *
 *   JVM_FindVa("../lib/jre", NULL);
 */
JVMSet * JVM_FindVa(Str dir1, ...)
{
    if (!dir1) {
        return JVM_Find2(NULL, 0);
    } else {
        JVMSet* jvms;
        Str arg = dir1;
        va_list va;
        Vector dirs;
        VECTOR_Init(&dirs, 0, NULL, NULL);
        va_start(va, dir1);
        while (arg) {
            if (!VECTOR_Add(&dirs, arg)) {
                VECTOR_Destroy(&dirs);
                return NULL;
            }
            arg = va_arg(va, Str);
        }
        va_end(va);
        jvms = JVM_Find2((Str*)VECTOR_GetElements(&dirs), VECTOR_Size(&dirs));
        VECTOR_Destroy(&dirs);
        return jvms;
    }
}
Example #7
0
/**
 * "Start element" callback for XML_Handle. Creates new entry in the element
 * stack. If an error has occured, simply increments skipDepth
 */
STATIC void XML_HandleStartElem(void * ctx, Str tag, const XMLAttr * a)
{
    XMLContext * context = (XMLContext*)ctx;
    if (context->error) {
        context->skipDepth++;
    } else {
        XMLTag * t = NULL;
        int depth = VECTOR_Size(&context->stack);
        if (!depth) {

            /* this is a root element */
            if (!context->rootTagName || !StrCmp(tag, context->rootTagName)) {
                
                /* we don't expect more than one root tag */
                ASSERT(!context->rootTag);
                if (!context->rootTag) {
                    t = context->rootHandler(context->rootContext, tag, a);
                }
            } else {
                Warning(TEXT("WARNING: invalid root tag <%s>, expected <%s>\n"),
                    tag, context->rootTagName);
            }
        } else {
            XMLTagCtx * parent;
            parent = (XMLTagCtx*)VECTOR_Get(&context->stack, depth-1);
            ASSERT(parent && parent->tag && parent->context == context);

            /* 
             * if tag handler is NULL, it means that the handler for the 
             * parent tag didn't expect any inner tags; we treat this as 
             * an error
             */
            if (parent->tag->handleTag) {
                t = parent->tag->handleTag(parent->tag, tag, a);
            }
        }

        if (t) {
            /* add new tag to the stack */
            XMLTagCtx * tagContext = MEM_New(XMLTagCtx);
            XMLTag * p = NULL;
            if (depth > 0) {
                p = ((XMLTagCtx*)VECTOR_Get(&context->stack,depth-1))->tag;
            }
            if (tagContext) {
                memset(tagContext, 0, sizeof(*tagContext));
                tagContext->context = context;
                tagContext->tag = t;
                tagContext->parent = p;
                if (VECTOR_Add(&context->stack, tagContext)) {
                    return;
                }
                MEM_Free(tagContext);
            }
            XML_FreeTag(t, p);
        }

        /* handle error */
        context->error = True;
        context->skipDepth++;
    }
}
Example #8
0
/**
 * Returns the number of discovered JVMs. The return value is always > 0
 */
int JVM_GetCount(const JVMSet * jvms)
{
    return VECTOR_Size(&jvms->found);
}
Example #9
0
/**
 * Discovers all available JVMs. If no JVMs are discovered, returns NULL.
 * In addition to the standard directories, also looks in the additional
 * directories specified by the dirs array. Note that this directory list
 * replaces the default list ("jre","../jre") used by JVM_Find, it does not
 * adds new directories to the list.
 */
JVMSet * JVM_Find2(const Str dirs[], int n)
{
    JVMSet * jvms = MEM_New(JVMSet);
    if (jvms) {
        memset(jvms, 0, sizeof(*jvms));
        if (VECTOR_Init(&jvms->found, 0, JVM_VectorEquals, JVM_VectorFree)) {

            /* Look for JVMs in the Windows registry */
            JVM_Discover(jvms);

            /* Look for JVMs in the additional directories */
            if (n > 0) {
                int i;
                StrBuf sb,sb2;
                Char* baseDir = NULL;
                STRBUF_Init(&sb);
                STRBUF_Init(&sb2);
                TRACE("JNILIB: checking special directories\n");
                for (i=0; i<n; i++) {
                    Str javaHome = NULL;
                    JvmPathType pathType = JVM_GetPathType(dirs[i]);
                    if (pathType == JvmPathRelative) {
                        LPTSTR filePath;
                        TRACE1("JNILIB: relative path: %s\n",dirs[i]);
                        if (baseDir) {
                            STRBUF_Copy(&sb, baseDir);
                        } else {
                            int separator;
                            JVM_GetModuleFileName(NULL,&sb);
                            STRBUF_Replace(&sb, '/', '\\');
                            separator = STRBUF_LastIndexOf(&sb,'\\');
                            STRBUF_SetLength(&sb,separator+1);
                            baseDir = STRBUF_Dup(&sb);
                            if (!baseDir) continue;
                            TRACE1("JNILIB: base dir: %s\n",baseDir);
                        }
                        STRBUF_Append(&sb, dirs[i]);
                        STRBUF_Replace(&sb, '/', '\\');
                        STRBUF_Alloc(&sb2, STRBUF_Length(&sb));
                        sb2.len = GetFullPathName(STRBUF_Text(&sb), 
                            sb2.alloc, sb2.s, &filePath);
                        ASSERT(sb2.len && sb2.s[0]);
                        javaHome = STRBUF_Text(&sb2);
                    } else if (pathType == JvmPathAbsolute) {
                        TRACE1("JNILIB: absolute path: %s\n",dirs[i]);
                        javaHome = dirs[i];
                    } else if (pathType == JvmPathSystem) {
                        /* directory on the system drive */
                        TRACE1("JNILIB: system path: %s\n",dirs[i]);
                        STRBUF_Alloc(&sb,GetSystemDirectory(NULL,0)+1);
                        STRBUF_SetLength(&sb,GetSystemDirectory(sb.s,sb.alloc));
                        STRBUF_Clear(&sb2);
                        STRBUF_AppendChar(&sb2,STRBUF_CharAt(&sb,0));
                        STRBUF_AppendChar(&sb2,':');
                        STRBUF_Append(&sb2, dirs[i]);
                        javaHome = STRBUF_Text(&sb2);
                    } else {
                        TRACE1("JNILIB: invalid path: %s\n",dirs[i]);
                        continue;
                    }
                    if (javaHome) {
                        TRACE1("JNILIB: Java home: %s\n",javaHome);
                        if (FILE_IsDir(javaHome)) {
                            JVM* jvm = JVM_CreateDirContext(javaHome);
                            if (jvm) {
                                jvm->flags |= JVM_FLAG_SPECIAL;
                                if (JVM_Add(jvms, jvm) && !jvms->specialVM) {
                                    jvms->specialVM = jvm;
                                }
                            }
                        } else {
                            TRACE1("JNILIB: no such directory: %s\n",javaHome);
                        }
                    }
                }
                MEM_Free(baseDir);
                STRBUF_Destroy(&sb);
                STRBUF_Destroy(&sb2);
            }

            /* Did we find anything? */
            if (!VECTOR_IsEmpty(&jvms->found)) {
                JVM_Sort(jvms, JVM_DefaultSort);
                TRACE1("JNILIB: found %d JVM(s)\n",VECTOR_Size(&jvms->found));
                return jvms;
            }
            TRACE("JNILIB: found no JVMs\n, sorry");
            VECTOR_Destroy(&jvms->found);
        }
        MEM_Free(jvms);
    }
    return NULL;
}
Example #10
0
/**
 * JVM discovery. Returns number of discovered JVMs
 */
STATIC int JVM_Discover(JVMSet * jvms)
{
    HKEY hRoot = NULL; 
    ULONG err = RegOpenKeyEx(HKLM, JRE_REG_KEY, 0, KEY_READ, &hRoot);
    char curVer[32];
    char ver[COUNT(curVer)];
    if (err == NO_ERROR) {
        ULONG nIndex = 0;

        /* determine the current version */
        ULONG t = REG_SZ;
        ULONG n = COUNT(ver);
        TRACE("JNILIB: checking current version of JRE...\n");
        err = RegQueryValueEx(hRoot,CURRENT_VERSION,0,&t,(LPBYTE)curVer,&n);
        if (err == NO_ERROR) {            
            JVM * jvm;
            curVer[COUNT(curVer)-1] = 0;  /* just in case */
            TRACE1("JNILIB: current Java version: %s\n", curVer);
            jvm = JVM_CreateRegContext(hRoot, curVer, False);
            if (jvm) {
                jvm->flags |= JVM_FLAG_DEFAULT;
                if (JVM_Add(jvms, jvm)) {
                    jvms->defaultVM = jvm;
                }
            }
        }

        TRACE("JNILIB: trying to find other versions of JRE...\n");
        while (RegEnumKey(hRoot, nIndex, ver, COUNT(ver)) == NO_ERROR) {
            if (StrCmp(ver, curVer)) {
                JVM_Add(jvms, JVM_CreateRegContext(hRoot, ver, False));
            }
            nIndex++;
        }
        RegCloseKey(hRoot);
    }

    err = RegOpenKeyEx(HKLM, JVM_REG_KEY, 0, KEY_READ, &hRoot);
    if (err == NO_ERROR) {
        ULONG nIndex = 0;

        /* determine the current version */
        curVer[0] = 0;
        if (!jvms->defaultVM) {
            ULONG t = REG_SZ;
            ULONG n = COUNT(ver);
            TRACE("JNILIB: checking current version of JVM...\n");
            err = RegQueryValueEx(hRoot,CURRENT_VERSION,0,&t,(LPBYTE)curVer,&n);
            if (err == NO_ERROR) {            
                JVM * jvm;
                curVer[COUNT(curVer)-1] = 0;  /* just in case */
                TRACE1("JNILIB: current Java version: %s\n", curVer);
                jvm = JVM_CreateRegContext(hRoot, curVer, True);
                if (jvm) {
                    jvm->flags |= JVM_FLAG_DEFAULT;
                    if (JVM_Add(jvms, jvm)) {
                        jvms->defaultVM = jvm;
                    }
                }
            }
        }

        TRACE("JNILIB: trying to find other versions of JVM...\n");
        while (RegEnumKey(hRoot, nIndex, ver, COUNT(ver)) == NO_ERROR) {
            if (StrCmp(ver, curVer)) {
                JVM_Add(jvms, JVM_CreateRegContext(hRoot, ver, True));
            }
            nIndex++;
        }
        RegCloseKey(hRoot);
    }

    return VECTOR_Size(&jvms->found);
}