BOOLEAN GetInfo (JNIEnv * jenv, PSID sid, LPSTR* ppName, LPSTR* ppDomain) { PORT_ACCESS_FROM_ENV (jenv); DWORD dwNameSize = 0; DWORD dwDomainNameSize = 0; SID_NAME_USE snu; if( !LookupAccountSid(NULL, sid, NULL, &dwNameSize, NULL, &dwDomainNameSize, &snu)) { if( ERROR_INSUFFICIENT_BUFFER != GetLastError() ) { return FALSE; } } *ppName = (LPSTR)hymem_allocate_memory(dwNameSize); if( NULL == ppName ) { return FALSE; } *ppDomain = (LPSTR)hymem_allocate_memory(dwDomainNameSize); if( NULL == ppName ) { DWORD err = GetLastError(); hymem_free_memory(*ppName); SetLastError(err); return FALSE; } if( !LookupAccountSid(NULL, sid, *ppName, &dwNameSize, *ppDomain, &dwDomainNameSize, &snu)) { DWORD err = GetLastError(); hymem_free_memory(*ppName); hymem_free_memory(*ppDomain); SetLastError(err); return FALSE; } return TRUE; }
/* ZLib interface to hymem_allocate_memory. */ void * zalloc (void *opaque, U_32 items, U_32 size) { PORT_ACCESS_FROM_PORT (((HyPortLibrary *) opaque)); return hymem_allocate_memory (items * size); }
char* read_attribute(JavaVM *vm, char *manifest,char *lwrmanifest, const char * target){ char *pos; char *end; char *value; char *tmp; int length; PORT_ACCESS_FROM_JAVAVM(vm); if(NULL == strstr(lwrmanifest,target)){ return NULL; } pos = manifest+ (strstr(lwrmanifest,target) - lwrmanifest); pos += strlen(target)+2;//": " end = strchr(pos, '\n'); while (end != NULL && *(end + 1) == ' ') { end = strchr(end + 1, '\n'); } if(NULL == end){ end = manifest + strlen(manifest); } length = end - pos; value = (char *)hymem_allocate_memory(sizeof(char)*(length+1)); tmp = value; end = strchr(pos, '\n'); while (end != NULL && *(end + 1) == ' ') { /* in windows, has '\r\n' in the end of line, omit '\r' */ if (*(end - 1) == '\r') { strncpy(tmp, pos, end - 1 - pos); tmp += end - 1 - pos; pos = end + 2; } else { strncpy(tmp, pos, end - pos); tmp += end - pos; pos = end + 2; } end = strchr(end + 1, '\n'); } if (NULL == end) { strcpy(tmp, pos); } else { /* in windows, has '\r\n' in the end of line, omit '\r' */ if (*(end - 1) == '\r') { end--; } strncpy(tmp, pos, end - pos); *(tmp + (end - pos)) = '\0'; } return value; }
JNIEXPORT jbyteArray JNICALL Java_org_apache_harmony_luni_platform_Environment_getEnvByName (JNIEnv *env, jclass obj, jbyteArray name){ DWORD dwRet,dwErr; LPTSTR envvalue; jsize len = 0; const DWORD BUFSIZE = 1024; jbyteArray byteArray = NULL; char *envname; PORT_ACCESS_FROM_ENV(env); len = (*env)->GetArrayLength(env, name); envname = (char *)hymem_allocate_memory(len+1); (*env)->GetByteArrayRegion(env, name, 0, len,(jbyte *)envname); envname[len] = 0; envvalue = (LPTSTR)hymem_allocate_memory(BUFSIZE*sizeof(TCHAR)); dwRet = GetEnvironmentVariable(envname, envvalue, BUFSIZE); if(0 == dwRet) { dwErr = GetLastError(); if( ERROR_ENVVAR_NOT_FOUND == dwErr ){ goto free_resource; } } else if(BUFSIZE < dwRet) { envvalue = (LPTSTR)hymem_reallocate_memory(envvalue, dwRet*sizeof(TCHAR)); if(NULL == envvalue){ goto free_resource; } dwRet = GetEnvironmentVariable((LPCSTR)envname, envvalue, dwRet); if(!dwRet){ goto free_resource; } } byteArray = (*env)->NewByteArray(env,dwRet); (*env)->SetByteArrayRegion(env,byteArray, 0, dwRet, (jbyte *)envvalue); free_resource: hymem_free_memory(envname); hymem_free_memory(envvalue); return byteArray; }
JNIEXPORT jint JNICALL Agent_OnLoad(JavaVM *vm, char *options, void *reserved){ PORT_ACCESS_FROM_JAVAVM(vm); VMI_ACCESS_FROM_JAVAVM(vm); jvmtiError jvmti_err; JNIEnv *env = NULL; static jvmtiEnv *jvmti; jvmtiCapabilities updatecapabilities; jint err = (*vm)->GetEnv(vm, (void **)&jnienv, JNI_VERSION_1_2); if(JNI_OK != err){ return err; } if(!gdata){ jvmtiCapabilities capabilities; jvmtiError jvmti_err; jvmtiEventCallbacks callbacks; gdata = hymem_allocate_memory(sizeof(AgentData)); //get jvmti environment err = (*vm)->GetEnv(vm, (void **)&jvmti, JVMTI_VERSION_1_0); if(JNI_OK != err){ return err; } gdata->jvmti = jvmti; //get JVMTI potential capabilities jvmti_err = (*jvmti)->GetPotentialCapabilities(jvmti, &capabilities); check_jvmti_error(env, jvmti_err, "Cannot get JVMTI potential capabilities."); gsupport_redefine = (capabilities.can_redefine_classes == 1); //set events callback function (void)memset(&callbacks, 0, sizeof(callbacks)); callbacks.ClassFileLoadHook = &callbackClassFileLoadHook; callbacks.VMInit = &callbackVMInit; jvmti_err = (*jvmti)->SetEventCallbacks(jvmti, &callbacks, sizeof(jvmtiEventCallbacks)); check_jvmti_error(env, jvmti_err, "Cannot set JVMTI event callback functions."); //enable classfileloadhook event jvmti_err = (*jvmti)->SetEventNotificationMode(jvmti, JVMTI_ENABLE, JVMTI_EVENT_VM_INIT, NULL); check_jvmti_error(env, jvmti_err, "Cannot set JVMTI VMInit event notification mode."); } err = Parse_Options(vm,jnienv, gdata->jvmti,options); //update capabilities JVMTI memset(&updatecapabilities, 0, sizeof(updatecapabilities)); updatecapabilities.can_generate_all_class_hook_events = 1; updatecapabilities.can_redefine_classes = gsupport_redefine; //FIXME VM doesnot support the capbility right now. //capabilities.can_redefine_any_class = 1; jvmti_err = (*jvmti)->AddCapabilities(jvmti, &updatecapabilities); check_jvmti_error(env, jvmti_err, "Cannot add JVMTI capabilities."); return err; }
/** * Concatenates a variable number of null-terminated strings into a single string * using the specified port library to allocate memory. The variable number of * strings arguments must be terminated by a single NULL value. * * @param portLibrary - The port library used to allocate memory. * @return The concatenated string or NULL if no memory can be allocated. */ char * str_concat (HyPortLibrary * portLibrary, ...) { PORT_ACCESS_FROM_PORT (portLibrary); va_list argp; char *concatenated; UDATA concatenatedSize = 0; /* Walk the variable arguments once to compute the final size */ va_start (argp, portLibrary); while (1) { char *chunk = va_arg (argp, char *); if (chunk) { concatenatedSize += (UDATA)strlen (chunk); } else { break; } } va_end (argp); /* Allocate concatenated space */ concatenated = hymem_allocate_memory (concatenatedSize + 1 /* for null terminator */ ); if (!concatenated) { return NULL; } concatenated[0] = '\0'; /* Walk again concatenating the pieces */ va_start (argp, portLibrary); while (1) { char *chunk = va_arg (argp, char *); if (chunk) { strcat (concatenated, chunk); } else { break; } } va_end (argp); return concatenated; }
static int prop_alloc(HyPortLibrary * portLibrary, key_value_pair* property, char* start, char* delim, char* end) { PORT_ACCESS_FROM_PORT (portLibrary); /* missing delimiter means the whole line is the key and value is empty */ size_t keyLength = (delim ? delim : end) - start; size_t valueLength = delim ? end - delim - 1 : 0; property->key = hymem_allocate_memory ((UDATA)(keyLength + 1)); property->value = hymem_allocate_memory ((UDATA)(valueLength + 1)); if (!property->key || !property->value) { return 0; } memcpy (property->key, start, keyLength); property->key[keyLength] = '\0'; if (delim) { memcpy (property->value, delim + 1, valueLength); } property->value[valueLength] = '\0'; return 1; }
JNIEXPORT jlong JNICALL Java_org_apache_harmony_luni_platform_OSMemory_malloc (JNIEnv * env, jobject thiz, jlong size) { PORT_ACCESS_FROM_ENV (env); void *address = hymem_allocate_memory ((UDATA) size); if (address == NULL) { throwNewOutOfMemoryError(env, "Insufficient memory available."); } return (jlong) ((IDATA) address); }
/** * This DLL is being loaded, do any initialization required. * This may be called more than once. */ JNIEXPORT jint JNICALL JNI_OnLoad (JavaVM * vm, void *reserved) { JniIDCache *idCache; JNIEnv *env; void *keyInitCountPtr = GLOBAL_DATA (keyInitCount); void **jclIdCache = GLOBAL_DATA (JCL_ID_CACHE); if ((*vm)->GetEnv (vm, (void **) &env, JNI_VERSION_1_2) == JNI_OK) { PORT_ACCESS_FROM_ENV (env); if (HY_VMLS_FNTBL (env)-> HYVMLSAllocKeys (env, keyInitCountPtr, jclIdCache, NULL)) { goto fail; } /* This allocate must actually be done by hymem_allocate_memory. */ idCache = (JniIDCache *) hymem_allocate_memory (sizeof (JniIDCache)); if (!idCache) goto fail2; memset (idCache, 0, sizeof (JniIDCache)); HY_VMLS_SET (env, *jclIdCache, idCache); /* Attach to the common library */ if (JNI_OK != ClearLibAttach (env)) { goto fail2; } return JNI_VERSION_1_2; } fail2: HY_VMLS_FNTBL (env)->HYVMLSFreeKeys (env, keyInitCountPtr, jclIdCache, NULL); fail: return 0; }
LPVOID QueryInfo (JNIEnv * jenv, HANDLE hToken, TOKEN_INFORMATION_CLASS klass) { PORT_ACCESS_FROM_ENV (jenv); DWORD dwSize; LPVOID pData = NULL; if( !GetTokenInformation(hToken, klass, NULL, 0, &dwSize) ) { DWORD dwErr = GetLastError(); if( ERROR_INSUFFICIENT_BUFFER != dwErr ) { return NULL; } } pData = hymem_allocate_memory(dwSize); if( !GetTokenInformation(hToken, klass, pData, dwSize, &dwSize) ) { DWORD dwErr = GetLastError(); hymem_free_memory(pData); SetLastError(dwErr); return NULL; } return pData; }
/** * Read the properties file specified by <tt>filename</tt> * into the array of <tt>properties</tt>, * using the specified port library to allocate memory. * The array is terminated with null-keyed element, * though one can obtain number of elements directly * via last argument. * * @param[in] portLibrary - The port library used to interact with the platform. * @param[in] filename - The file from which to read data using hyfile* functions. * @param[out] properties - An array that will contain property file entries. * @param[out] number - Optional parameter, number of elements in the returned array. * * @return JNI_OK on success, or a JNI error code on failure. */ jint properties_load(HyPortLibrary * portLibrary, const char *filename, key_value_pair** properties, U_32 *number) { PORT_ACCESS_FROM_PORT (portLibrary); void *handle; I_64 seekResult; IDATA fileSize; char *scanCursor, *scanLimit; char *start, *delim, *end; key_value_pair *props; unsigned arraySize; unsigned count = 0; jint status = JNI_OK; /* Determine the file size, fail if > 2G */ seekResult = hyfile_length (filename); if ((seekResult <= 0) || (seekResult > 0x7FFFFFFF)) { return JNI_ERR; } scanCursor = hymmap_map_file(filename, &handle); if (!scanCursor) { return JNI_ERR; } #ifdef ZOS /* Convert the scan buffer into ASCII */ scanCursor = e2a(scanCursor, seekResult); #endif fileSize = (IDATA) seekResult; arraySize = fileSize/50 + 1; props = hymem_allocate_memory(sizeof(key_value_pair)*(arraySize + 1)); if (!props) { status = JNI_ENOMEM; goto finish; } start = end = scanCursor; delim = NULL; scanLimit = scanCursor + fileSize; do { while (scanCursor < scanLimit) { switch(*scanCursor) { case '\r': case '\n': end = scanCursor; goto read_line; case '=': /* remember only first occurrence which is not key itself */ if (delim == NULL && scanCursor > start) { delim = scanCursor; } default: ++scanCursor; continue; } } read_line: if (scanCursor > start && start != delim && *start != '#' && *start != '!') /* line is not empty, well formed and not commented out */ { if (end == start) { /* the last line ends with EOF */ end = scanLimit; } if (count == arraySize) { void* re_props; arraySize += arraySize/2 + 1; re_props = hymem_reallocate_memory(props, sizeof(key_value_pair)*(arraySize + 1)); if (!re_props) { status = JNI_ENOMEM; goto finish; } props = re_props; } if (!prop_alloc(portLibrary, props + count, start, delim, end)) { status = JNI_ENOMEM; goto finish; } ++count; } start = end = ++scanCursor; delim = NULL; } while (scanCursor < scanLimit); /*set terminating NULL*/ props[count].key = NULL; finish: hymmap_unmap_file(handle); if (status != JNI_OK) { properties_free(portLibrary, props); } else { *properties = props; if (number){ *number = count; } } return status; }
jint Parse_Options(JavaVM *vm, JNIEnv *env, jvmtiEnv *jvmti, const char *agent){ PORT_ACCESS_FROM_JAVAVM(vm); VMI_ACCESS_FROM_JAVAVM(vm); AgentList *new_elem = (AgentList *)hymem_allocate_memory(sizeof(AgentList)); char *agent_cpy = (char *)hymem_allocate_memory(sizeof(char)*(strlen(agent)+1)); char *jar_name, *manifest; char *options = NULL; char *class_name, *bootclasspath, *str_support_redefine; char *bootclasspath_item; char *classpath; char *classpath_cpy; int support_redefine = 0; char *pos; char *lwrmanifest; strcpy(agent_cpy, agent); //parse jar name and options pos = strchr(agent_cpy, '='); if(pos>0){ *pos++ = 0; options = (char *)hymem_allocate_memory(sizeof(char) * (strlen(pos)+1)); strcpy(options, pos); } jar_name =agent_cpy; //read jar files, find manifest entry and read bytes //read attributes(premain class, support redefine, bootclasspath) manifest = Read_Manifest(vm,env, jar_name); lwrmanifest = (char *)hymem_allocate_memory(sizeof(char) * (strlen(manifest)+1)); strcpy(lwrmanifest,manifest); strlower(lwrmanifest); //jar itself added to bootclasspath check_jvmti_error(env, (*jvmti)->GetSystemProperty(jvmti,"java.class.path",&classpath),"Failed to get classpath."); classpath_cpy = (char *)hymem_allocate_memory((sizeof(char)*(strlen(classpath)+strlen(jar_name)+2))); strcpy(classpath_cpy,classpath); #if defined(WIN32) || defined(WIN64) strcat(classpath_cpy,";"); #else strcat(classpath_cpy,":"); #endif strcat(classpath_cpy,jar_name); check_jvmti_error(env, (*jvmti)->SetSystemProperty(jvmti, "java.class.path",classpath_cpy),"Failed to set classpath."); hymem_free_memory(classpath_cpy); hymem_free_memory(jar_name); //save options, save class name, add to agent list class_name = read_attribute(vm, manifest, lwrmanifest,"premain-class"); if(NULL == class_name){ hymem_free_memory(lwrmanifest); hymem_free_memory(manifest); (*env)->FatalError(env,"Cannot find Premain-Class attribute."); } new_elem->option = options; new_elem->class_name = class_name; new_elem->next = NULL; tail->next = new_elem; tail = new_elem; //calculate support redefine str_support_redefine = read_attribute(vm, manifest, lwrmanifest,"can-redefine-classes"); if(NULL != str_support_redefine){ support_redefine = str2bol(str_support_redefine); hymem_free_memory(str_support_redefine); } gsupport_redefine &= support_redefine; //add bootclasspath bootclasspath = read_attribute(vm, manifest, lwrmanifest,"boot-class-path"); if (NULL != bootclasspath){ #if defined(WIN32) || defined(WIN64) // On Windows the agent jar path can have a mixture of forward and back slashes. // For ease, convert forward slashes to back slashes char *currentSlash = strchr(jar_name, '/'); while (currentSlash) { *currentSlash = '\\'; currentSlash = strchr(currentSlash, '/'); } #endif bootclasspath_item = strtok(bootclasspath, " "); while(NULL != bootclasspath_item){ if ((bootclasspath_item[0] != DIR_SEPARATOR) && (strrchr(jar_name, DIR_SEPARATOR))) { // This is not an absolute path, so add this relative path to the path of the agent library int lastSeparatorOff = strrchr(jar_name, DIR_SEPARATOR) - jar_name + 1; int size = lastSeparatorOff + strlen(bootclasspath_item) + 1; char *jarPath = (char *)hymem_allocate_memory(size); memcpy(jarPath, jar_name, lastSeparatorOff); strcpy(jarPath + lastSeparatorOff, bootclasspath_item); check_jvmti_error(env, (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, jarPath),"Failed to add bootstrap classpath."); hymem_free_memory(jarPath); } else { // This is either an absolute path of jar_name has not path before the filename check_jvmti_error(env, (*jvmti)->AddToBootstrapClassLoaderSearch(jvmti, bootclasspath_item),"Failed to add bootstrap classpath."); } bootclasspath_item = strtok(NULL, " "); } hymem_free_memory(bootclasspath); } hymem_free_memory(lwrmanifest); hymem_free_memory(manifest); return 0; }
char* Read_Manifest(JavaVM *vm, JNIEnv *env,const char *jar_name){ I_32 retval; #ifndef HY_ZIP_API HyZipFile zipFile; HyZipEntry zipEntry; #else VMIZipFile zipFile; VMIZipEntry zipEntry; #endif char *result; int size = 0; char errorMessage[1024]; /* Reach for the VM interface */ VMI_ACCESS_FROM_JAVAVM(vm); PORT_ACCESS_FROM_JAVAVM(vm); #ifdef HY_ZIP_API VMIZipFunctionTable *zipFuncs = (*VMI)->GetZipFunctions(VMI); #endif /* HY_ZIP_API */ /* open zip file */ #ifndef HY_ZIP_API retval = zip_openZipFile(privatePortLibrary, (char *)jar_name, &zipFile, NULL); #else /* HY_ZIP_API */ retval = zipFuncs->zip_openZipFile(VMI, (char *)jar_name, &zipFile, 0); #endif /* HY_ZIP_API */ if(retval){ sprintf(errorMessage,"failed to open file:%s, %d\n", jar_name, retval); (*env)->FatalError(env, errorMessage); return NULL; } /* get manifest entry */ #ifndef HY_ZIP_API zip_initZipEntry(privatePortLibrary, &zipEntry); retval = zip_getZipEntry(privatePortLibrary, &zipFile, &zipEntry, "META-INF/MANIFEST.MF", TRUE); #else /* HY_ZIP_API */ zipFuncs->zip_initZipEntry(VMI, &zipEntry); retval = zipFuncs->zip_getZipEntry(VMI, &zipFile, &zipEntry, "META-INF/MANIFEST.MF", ZIP_FLAG_READ_DATA_POINTER); #endif /* HY_ZIP_API */ if (retval) { #ifndef HY_ZIP_API zip_freeZipEntry(PORTLIB, &zipEntry); #else /* HY_ZIP_API */ zipFuncs->zip_freeZipEntry(VMI, &zipEntry); #endif /* HY_ZIP_API */ sprintf(errorMessage,"failed to get entry: %d\n", retval); (*env)->FatalError(env, errorMessage); return NULL; } /* read bytes */ size = zipEntry.uncompressedSize; result = (char *)hymem_allocate_memory(size*sizeof(char) + 1); #ifndef HY_ZIP_API retval = zip_getZipEntryData(privatePortLibrary, &zipFile, &zipEntry, (unsigned char*)result, size); #else /* HY_ZIP_API */ retval = zipFuncs->zip_getZipEntryData(VMI, &zipFile, &zipEntry, (unsigned char*)result, size); #endif /* HY_ZIP_API */ if(retval){ #ifndef HY_ZIP_API zip_freeZipEntry(PORTLIB, &zipEntry); #else /* HY_ZIP_API */ zipFuncs->zip_freeZipEntry(VMI, &zipEntry); #endif /* HY_ZIP_API */ sprintf(errorMessage,"failed to get bytes from zip entry, %d\n", zipEntry.extraFieldLength); (*env)->FatalError(env, errorMessage); return NULL; } result[size] = '\0'; /* free resource */ #ifndef HY_ZIP_API zip_freeZipEntry(privatePortLibrary, &zipEntry); retval = zip_closeZipFile(privatePortLibrary, &zipFile); #else /* HY_ZIP_API */ zipFuncs->zip_freeZipEntry(VMI, &zipEntry); retval = zipFuncs->zip_closeZipFile(VMI, &zipFile); #endif /* HY_ZIP_API */ if (retval) { sprintf(errorMessage,"failed to close zip file: %s, %d\n", jar_name, retval); (*env)->FatalError(env, errorMessage); return NULL; } return result; }