Java Code Examples for com.sun.jna.Pointer#share()

The following examples show how to use com.sun.jna.Pointer#share() . You can vote up the ones you like or vote down the ones you don't like, and go to the original project or source file by following the links above each example. You may check out the related API usage on the sidebar.
Example 1
Source File: DirectoryFileIO.java    From unidbg with Apache License 2.0 6 votes vote down vote up
@Override
public int getdirentries64(Pointer buf, int bufSize) {
    int offset = 0;
    for (Iterator<DirectoryFileIO.DirectoryEntry> iterator = this.entries.iterator(); iterator.hasNext(); ) {
        DirectoryFileIO.DirectoryEntry entry = iterator.next();
        byte[] data = entry.name.getBytes(StandardCharsets.UTF_8);
        long d_reclen = ARM.alignSize(data.length + 24, 8);

        if (offset + d_reclen >= bufSize) {
            break;
        }

        Dirent dirent = new Dirent(buf.share(offset));
        dirent.d_fileno = 1;
        dirent.d_reclen = (short) d_reclen;
        dirent.d_type = entry.isFile ? Dirent.DT_REG : Dirent.DT_DIR;
        dirent.d_namlen = (short) (data.length);
        dirent.d_name = Arrays.copyOf(data, data.length + 1);
        dirent.pack();
        offset += d_reclen;

        iterator.remove();
    }

    return offset;
}
 
Example 2
Source File: BaseDarwinFileIO.java    From unidbg with Apache License 2.0 6 votes vote down vote up
protected final int listxattr(File dest, Pointer namebuf, int size) {
    try {
        DarwinFileAttr attr = loadAttr(dest);
        if (attr == null || attr.xattr == null) {
            return 0;
        }
        int ret = 0;
        Pointer buffer = namebuf;
        for (String name : attr.xattr.keySet()) {
            byte[] data = name.getBytes(StandardCharsets.UTF_8);
            ret += (data.length + 1);

            if (buffer != null && ret <= size) {
                buffer.write(0, Arrays.copyOf(data, data.length + 1), 0, data.length + 1);
                buffer = buffer.share(data.length + 1);
            }
        }
        return ret;
    } catch (IOException e) {
        throw new IllegalStateException(e);
    }
}
 
Example 3
Source File: ArmHook.java    From unidbg with Apache License 2.0 6 votes vote down vote up
@Override
public final long handle(Emulator<?> emulator) {
    Unicorn u = emulator.getUnicorn();
    Pointer sp = UnicornPointer.register(emulator, ArmConst.UC_ARM_REG_SP);
    try {
        HookStatus status = hook(emulator);
        if (status.forward || !enablePostCall) {
            sp = sp.share(-4);
            sp.setInt(0, (int) status.jump);
        } else {
            sp = sp.share(-4);
            sp.setInt(0, 0);
        }

        return status.returnValue;
    } finally {
        u.reg_write(ArmConst.UC_ARM_REG_SP, ((UnicornPointer) sp).peer);
    }
}
 
Example 4
Source File: Arm64Hook.java    From unidbg with Apache License 2.0 6 votes vote down vote up
@Override
public final long handle(Emulator<?> emulator) {
    Unicorn u = emulator.getUnicorn();
    Pointer sp = UnicornPointer.register(emulator, Arm64Const.UC_ARM64_REG_SP);
    try {
        HookStatus status = hook(emulator);
        if (status.forward || !enablePostCall) {
            sp = sp.share(-8);
            sp.setLong(0, status.jump);
        } else {
            sp = sp.share(-8);
            sp.setLong(0, 0);
        }

        return status.returnValue;
    } finally {
        u.reg_write(Arm64Const.UC_ARM64_REG_SP, ((UnicornPointer) sp).peer);
    }
}
 
Example 5
Source File: StringListStruct.java    From domino-jna with Apache License 2.0 6 votes vote down vote up
/**
 * Converts all string list values to a Java {@link List}
 * 
 * @return list
 */
public List<String> getValues() {
	if (count==0)
		return Collections.emptyList();

	List<String> strValues = new ArrayList<String>(count);
	int offset = 0;
	
	Pointer stringStartPtr = first;
	
	for (int i=0; i<count; i++) {
		while (stringStartPtr.getByte(offset)!=0) {
			offset++;
		}
		String currStr = NotesStringUtils.fromLMBCS(stringStartPtr, offset);
		strValues.add(currStr);
		stringStartPtr = stringStartPtr.share(offset+1);
	}
	return strValues;
}
 
Example 6
Source File: ThumbIntercept.java    From unidbg with Apache License 2.0 6 votes vote down vote up
private void evalBL(Unicorn u, boolean x, Emulator<?> emulator) {
    Pointer sp = UnicornPointer.register(emulator, ArmConst.UC_ARM_REG_SP);
    try {
        Pointer pc = UnicornPointer.register(emulator, ArmConst.UC_ARM_REG_PC);
        u.reg_write(ArmConst.UC_ARM_REG_LR, ((UnicornPointer) pc.share(2)).peer | 1L); // thumb
        sp = sp.share(-4);

        Arm.OpInfo opInfo = (Arm.OpInfo) this.insn.operands;
        int off = opInfo.op[0].value.imm;
        pc = pc.share(off).share(-2);
        if (!x) {
            pc = pc.share(1); // thumb
        }
        sp.setPointer(0, pc);
    } finally {
        u.reg_write(ArmConst.UC_ARM_REG_SP, ((UnicornPointer) sp).peer);
    }
}
 
Example 7
Source File: ItemDecoder.java    From domino-jna with Apache License 2.0 5 votes vote down vote up
public static List<Object> decodeNumberList(Pointer ptr, int valueLength) {
	NotesRangeStruct range = NotesRangeStruct.newInstance(ptr);
	range.read();
	
	//read number of list and range entries in range
	int listEntriesAsInt = range.ListEntries & 0xffff;
	int rangeEntriesAsInt = range.RangeEntries & 0xffff;
	
	//skip range header
	Pointer ptrAfterRange = ptr.share(NotesConstants.rangeSize);
	
	//we create an object list, because number ranges contain double[] array
	//(not sure whether number ranges exist in real life)
	List<Object> numberValues = new ArrayList<Object>(listEntriesAsInt + rangeEntriesAsInt);
	for (int t=0; t<listEntriesAsInt; t++) {
		double numVal = ptrAfterRange.getDouble(t * 8);
		numberValues.add(numVal);
	}
	//skip list entries part of the buffer
	Pointer ptrAfterListEntries = ptrAfterRange.share(8 * listEntriesAsInt);
	
	for (int t=0; t<rangeEntriesAsInt; t++) {
		Pointer ptrListEntry = ptrAfterListEntries.share(t * NotesConstants.numberPairSize);
		NotesNumberPairStruct numPair = NotesNumberPairStruct.newInstance(ptrListEntry);
		numPair.read();
		double lower = numPair.Lower;
		double upper = numPair.Upper;
		
		numberValues.add(new double[] {lower, upper});
	}
	
	return numberValues;
}
 
Example 8
Source File: ArmIntercept.java    From unidbg with Apache License 2.0 5 votes vote down vote up
private void evalPush(Unicorn u, Emulator<?> emulator) {
    Pointer sp = UnicornPointer.register(emulator, ArmConst.UC_ARM_REG_SP);
    Arm.OpInfo opInfo = (Arm.OpInfo) this.insn.operands;
    List<Arm.Operand> operandList = new ArrayList<>(opInfo.op.length);
    Collections.addAll(operandList, opInfo.op);
    Collections.reverse(operandList);
    try {
        for (Arm.Operand operand : operandList) {
            sp = sp.share(-4);
            sp.setPointer(0, UnicornPointer.register(emulator, operand.value.reg));
        }
    } finally {
        u.reg_write(ArmConst.UC_ARM_REG_SP, ((UnicornPointer) sp).peer);
    }
}
 
Example 9
Source File: NotesStringUtils.java    From domino-jna with Apache License 2.0 5 votes vote down vote up
/**
 * Reads a list of null terminated strings in LMBCS format at the specified pointer
 * 
 * @param inPtr pointer
 * @param numEntries number of null terminated strings
 * @return string list
 */
public static List<String> fromLMBCSStringList(Pointer inPtr, int numEntries) {
	List<String> stringList = new ArrayList<String>();
	
	Pointer ptrStartOfString = inPtr;
	
	for (int i=0; i<numEntries; i++) {
		int currStringOffset = 0;
		
		while(true) {
			byte b = ptrStartOfString.getByte(currStringOffset);
			currStringOffset++;
			if (b==0) {
				break;
			}
		}
		
		String currString = fromLMBCS(ptrStartOfString, currStringOffset-1);
		stringList.add(currString);
		
		if ((i+1)<numEntries) {
			ptrStartOfString = ptrStartOfString.share(currStringOffset);
		}
		else {
			break;
		}
	}
	return stringList;
}
 
Example 10
Source File: ARM32SyscallHandler.java    From unidbg with Apache License 2.0 5 votes vote down vote up
private int poll(Unicorn u, Emulator<?> emulator) {
    Pointer fds = UnicornPointer.register(emulator, ArmConst.UC_ARM_REG_R0);
    int nfds = ((Number) u.reg_read(ArmConst.UC_ARM_REG_R1)).intValue();
    int timeout = ((Number) u.reg_read(ArmConst.UC_ARM_REG_R2)).intValue();
    int count = 0;
    for (int i = 0; i < nfds; i++) {
        Pointer pollfd = fds.share(i * 8);
        int fd = pollfd.getInt(0);
        short events = pollfd.getShort(4); // requested events
        if (log.isDebugEnabled()) {
            log.debug("poll fds=" + fds + ", nfds=" + nfds + ", timeout=" + timeout + ", fd=" + fd + ", events=" + events);
        }
        if (fd < 0) {
            pollfd.setShort(6, (short) 0);
        } else {
            short revents = 0;
            if((events & POLLOUT) != 0) {
                revents = POLLOUT;
            } else if ((events & POLLIN) != 0) {
                revents = POLLIN;
            }
            pollfd.setShort(6, revents); // returned events
            count++;
        }
    }
    return count;
}
 
Example 11
Source File: ARM64SyscallHandler.java    From unidbg with Apache License 2.0 5 votes vote down vote up
protected int uname(Emulator<?> emulator) {
    RegisterContext context = emulator.getContext();
    Pointer buf = context.getPointerArg(0);
    if (log.isDebugEnabled()) {
        log.debug("uname buf=" + buf);
    }

    final int SYS_NMLN = 65;

    Pointer sysName = buf.share(0);
    sysName.setString(0, "Linux"); /* Operating system name (e.g., "Linux") */

    Pointer nodeName = sysName.share(SYS_NMLN);
    nodeName.setString(0, "localhost"); /* Name within "some implementation-defined network" */

    Pointer release = nodeName.share(SYS_NMLN);
    release.setString(0, "1.0.0-unidbg"); /* Operating system release (e.g., "2.6.28") */

    Pointer version = release.share(SYS_NMLN);
    version.setString(0, "#1 SMP PREEMPT Thu Apr 19 14:36:58 CST 2018"); /* Operating system version */

    Pointer machine = version.share(SYS_NMLN);
    machine.setString(0, "arm64-v8a"); /* Hardware identifier */

    Pointer domainName = machine.share(SYS_NMLN);
    domainName.setString(0, ""); /* NIS or YP domain name */

    return 0;
}
 
Example 12
Source File: NotesSearchKeyEncoder.java    From domino-jna with Apache License 2.0 5 votes vote down vote up
/**
 * Searching with number range keys is not supported yet (R9), as the 
 * <a href="http://www-12.lotus.com/ldd/doc/domino_notes/9.0/api90ref.nsf/70cfe734675fd140852561ce00718042/35abe18f9580ca2d8525622e0062c48d?OpenDocument">documentation</a> says.
 * 
 * @param itemOut output stream for ITEM structure
 * @param valueDataOut output stream for search key value
 * @param currKey search key
 * @throws Exception in case of errors
 */
private static void addNumberRangeKey(OutputStream itemOut, OutputStream valueDataOut, double[] currKey) throws Exception {
	if (currKey.length!=2)
		throw new IllegalArgumentException("Double search key array must have exactly 2 elements. We found "+currKey.length);
	
	Memory itemMem = new Memory(NotesConstants.tableItemSize);
	NotesTableItemStruct item = NotesTableItemStruct.newInstance(itemMem);
	item.NameLength = 0;
	item.ValueLength = (short) ((NotesConstants.rangeSize + NotesConstants.numberPairSize + 2) & 0xffff);
	item.write();

	for (int i=0; i<NotesConstants.tableItemSize; i++) {
		itemOut.write(itemMem.getByte(i));
	}

	Memory valueMem = new Memory(NotesConstants.rangeSize + NotesConstants.numberPairSize + 2);
	valueMem.setShort(0, (short) NotesItem.TYPE_NUMBER_RANGE);

	Pointer rangePtr = valueMem.share(2);
	NotesRangeStruct range = NotesRangeStruct.newInstance(rangePtr);
	range.ListEntries = 0;
	range.RangeEntries = 1;
	range.write();

	Pointer pairPtr = rangePtr.share(NotesConstants.rangeSize);
	NotesNumberPairStruct pair = NotesNumberPairStruct.newInstance(pairPtr);
	pair.Lower = currKey[0];
	pair.Upper = currKey[1];
	pair.write();
	
	for (int i=0; i<valueMem.size(); i++) {
		valueDataOut.write(valueMem.getByte(i));
	}
}
 
Example 13
Source File: ArmLD64.java    From unidbg with Apache License 2.0 4 votes vote down vote up
private long dlopen(Memory memory, String filename, Emulator<?> emulator) {
    Pointer pointer = UnicornPointer.register(emulator, Arm64Const.UC_ARM64_REG_SP);
    try {
        Module module = memory.dlopen(filename, false);
        pointer = pointer.share(-8); // return value
        if (module == null) {
            pointer.setLong(0, 0);

            pointer = pointer.share(-8); // NULL-terminated
            pointer.setLong(0, 0);

            if (!"libnetd_client.so".equals(filename)) {
                log.info("dlopen failed: " + filename);
            } else if(log.isDebugEnabled()) {
                log.debug("dlopen failed: " + filename);
            }
            this.error.setString(0, "Resolve library " + filename + " failed");
            return 0;
        } else {
            pointer.setLong(0, module.base);

            pointer = pointer.share(-8); // NULL-terminated
            pointer.setLong(0, 0);

            for (Module md : memory.getLoadedModules()) {
                LinuxModule m = (LinuxModule) md;
                if (!m.getUnresolvedSymbol().isEmpty()) {
                    continue;
                }
                for (InitFunction initFunction : m.initFunctionList) {
                    if (log.isDebugEnabled()) {
                        log.debug("[" + m.name + "]PushInitFunction: 0x" + Long.toHexString(initFunction.getAddress()));
                    }
                    pointer = pointer.share(-8); // init array
                    pointer.setLong(0, initFunction.getAddress());
                }
                m.initFunctionList.clear();
            }

            return module.base;
        }
    } finally {
        unicorn.reg_write(Arm64Const.UC_ARM64_REG_SP, ((UnicornPointer) pointer).peer);
    }
}
 
Example 14
Source File: ARM64SyscallHandler.java    From unidbg with Apache License 2.0 4 votes vote down vote up
private int pthread_clone(Emulator<?> emulator) {
    RegisterContext context = emulator.getContext();
    int flags = context.getIntArg(0);
    Pointer child_stack = context.getPointerArg(1);
    List<String> list = new ArrayList<>();
    if ((flags & CLONE_VM) != 0) {
        list.add("CLONE_VM");
    }
    if ((flags & CLONE_FS) != 0) {
        list.add("CLONE_FS");
    }
    if ((flags & CLONE_FILES) != 0) {
        list.add("CLONE_FILES");
    }
    if ((flags & CLONE_SIGHAND) != 0) {
        list.add("CLONE_SIGHAND");
    }
    if ((flags & CLONE_PTRACE) != 0) {
        list.add("CLONE_PTRACE");
    }
    if ((flags & CLONE_VFORK) != 0) {
        list.add("CLONE_VFORK");
    }
    if ((flags & CLONE_PARENT) != 0) {
        list.add("CLONE_PARENT");
    }
    if ((flags & CLONE_THREAD) != 0) {
        list.add("CLONE_THREAD");
    }
    if ((flags & CLONE_NEWNS) != 0) {
        list.add("CLONE_NEWNS");
    }
    if ((flags & CLONE_SYSVSEM) != 0) {
        list.add("CLONE_SYSVSEM");
    }
    if ((flags & CLONE_SETTLS) != 0) {
        list.add("CLONE_SETTLS");
    }
    if ((flags & CLONE_PARENT_SETTID) != 0) {
        list.add("CLONE_PARENT_SETTID");
    }
    if ((flags & CLONE_CHILD_CLEARTID) != 0) {
        list.add("CLONE_CHILD_CLEARTID");
    }
    if ((flags & CLONE_DETACHED) != 0) {
        list.add("CLONE_DETACHED");
    }
    if ((flags & CLONE_UNTRACED) != 0) {
        list.add("CLONE_UNTRACED");
    }
    if ((flags & CLONE_CHILD_SETTID) != 0) {
        list.add("CLONE_CHILD_SETTID");
    }
    if ((flags & CLONE_STOPPED) != 0) {
        list.add("CLONE_STOPPED");
    }
    int threadId = ++this.threadId;

    Pointer fn = child_stack.getPointer(0);
    child_stack = child_stack.share(4);
    Pointer arg = child_stack.getPointer(0);
    child_stack = child_stack.share(4);

    log.info("pthread_clone child_stack=" + child_stack + ", thread_id=" + threadId + ", fn=" + fn + ", arg=" + arg + ", flags=" + list);
    threadMap.put(threadId, new LinuxThread(child_stack, fn, arg));
    lastThread = threadId;
    return threadId;
}
 
Example 15
Source File: ArmLD.java    From unidbg with Apache License 2.0 4 votes vote down vote up
private long dlopen(Memory memory, String filename, Emulator<?> emulator) {
    Pointer pointer = UnicornPointer.register(emulator, ArmConst.UC_ARM_REG_SP);
    try {
        Module module = memory.dlopen(filename, false);
        pointer = pointer.share(-4); // return value
        if (module == null) {
            pointer.setInt(0, 0);

            pointer = pointer.share(-4); // NULL-terminated
            pointer.setInt(0, 0);

            if (!"libnetd_client.so".equals(filename)) {
                log.info("dlopen failed: " + filename);
            } else if(log.isDebugEnabled()) {
                log.debug("dlopen failed: " + filename);
            }
            this.error.setString(0, "Resolve library " + filename + " failed");
            return 0;
        } else {
            pointer.setInt(0, (int) module.base);

            pointer = pointer.share(-4); // NULL-terminated
            pointer.setInt(0, 0);

            for (Module md : memory.getLoadedModules()) {
                LinuxModule m = (LinuxModule) md;
                if (!m.getUnresolvedSymbol().isEmpty()) {
                    continue;
                }
                for (InitFunction initFunction : m.initFunctionList) {
                    if (log.isDebugEnabled()) {
                        log.debug("[" + m.name + "]PushInitFunction: 0x" + Long.toHexString(initFunction.getAddress()));
                    }
                    pointer = pointer.share(-4); // init array
                    pointer.setInt(0, (int) initFunction.getAddress());
                }
                m.initFunctionList.clear();
            }

            return module.base;
        }
    } finally {
        unicorn.reg_write(ArmConst.UC_ARM_REG_SP, ((UnicornPointer) pointer).peer);
    }
}
 
Example 16
Source File: NotesLookupResultBufferDecoder.java    From domino-jna with Apache License 2.0 4 votes vote down vote up
/**
	 * Decodes an ITEM_VALUE_TABLE structure, which contains an ordered list of item values
	 * 
	 * @param bufferPtr pointer to a buffer
	 * @param convertStringsLazily true to delay string conversion until the first use
	 * @param convertNotesTimeDateToCalendar true to convert {@link NotesTimeDate} values to {@link Calendar}
	 * @param decodeAllValues true to decode all values in the buffer
	 * @return item value table data
	 */
	public static IItemValueTableData decodeItemValueTable(Pointer bufferPtr,
			boolean convertStringsLazily, boolean convertNotesTimeDateToCalendar, boolean decodeAllValues) {
		int bufferPos = 0;
		
		//skip item value table header
		bufferPos += NotesConstants.itemValueTableSize;
		
//		The information in a view summary of values is as follows:
//
//			ITEM_VALUE_TABLE containing header information (total length of summary, number of items in summary)
//			WORD containing the length of item #1 (including data type)
//			WORD containing the length of item #2 (including data type)
//			WORD containing the length of item #3 (including data type)
//			...
//			USHORT containing the data type of item #1
//			value of item #1
//			USHORT containing the data type of item #2
//			value of item #2
//			USHORT containing the data type of item #3
//			value of item #3
//			....
		
		int totalBufferLength = bufferPtr.getShort(0) & 0xffff;
		int itemsCount = bufferPtr.getShort(2) & 0xffff;
		
		int[] itemValueLengths = new int[itemsCount];
		//we don't have any item names:
		int[] itemNameLengths = null;
		
		//read all item lengths
		for (int j=0; j<itemsCount; j++) {
			//convert USHORT to int without sign
			itemValueLengths[j] = bufferPtr.getShort(bufferPos) & 0xffff;
			bufferPos += 2;
		}

		ItemValueTableDataImpl data = new ItemValueTableDataImpl(convertStringsLazily);
		data.setPreferNotesTimeDates(!convertNotesTimeDateToCalendar);
		data.m_totalBufferLength = totalBufferLength;
		data.m_itemsCount = itemsCount;

		Pointer itemValuePtr = bufferPtr.share(bufferPos);
		populateItemValueTableData(itemValuePtr, itemsCount, itemNameLengths, itemValueLengths, data,
				convertStringsLazily, convertNotesTimeDateToCalendar, decodeAllValues);

		return data;
	}
 
Example 17
Source File: ItemDecoder.java    From domino-jna with Apache License 2.0 4 votes vote down vote up
public static List<Object> decodeTimeDateListAsNotesTimeDate(Pointer ptr) {
	NotesRangeStruct range = NotesRangeStruct.newInstance(ptr);
	range.read();
	
	//read number of list and range entries in range
	int listEntriesAsInt = range.ListEntries & 0xffff;
	int rangeEntriesAsInt = range.RangeEntries & 0xffff;
	
	//skip range header
	Pointer ptrAfterRange = ptr.share(NotesConstants.rangeSize);
	
	List<Object> calendarValues = new ArrayList<Object>(listEntriesAsInt + rangeEntriesAsInt);
	
	for (int t=0; t<listEntriesAsInt; t++) {
		Pointer ptrListEntry = ptrAfterRange.share(t * NotesConstants.timeDateSize);
		int[] innards = ptrListEntry.getIntArray(0, 2);
		calendarValues.add(new NotesTimeDate(innards));
	}
	
	//move position to the range data
	Pointer ptrAfterListEntries = ptrAfterRange.share(listEntriesAsInt * NotesConstants.timeDateSize);
	
	for (int t=0; t<rangeEntriesAsInt; t++) {
		Pointer ptrRangeEntry = ptrAfterListEntries.share(t * NotesConstants.timeDatePairSize);
		NotesTimeDatePairStruct timeDatePair = NotesTimeDatePairStruct.newInstance(ptrRangeEntry);
		timeDatePair.read();
		
		NotesTimeDateStruct lowerTimeDateStruct = timeDatePair.Lower;
		NotesTimeDateStruct upperTimeDateStruct = timeDatePair.Upper;
		
		int[] lowerTimeDateInnards = lowerTimeDateStruct.Innards;
		int[] upperTimeDateInnards = upperTimeDateStruct.Innards;
		
		NotesTimeDate lowerTimeDate = new NotesTimeDate(lowerTimeDateInnards);
		NotesTimeDate upperTimeDate = new NotesTimeDate(upperTimeDateInnards);
		
		calendarValues.add(new NotesDateRange(lowerTimeDate, upperTimeDate));
	}
	
	return calendarValues;

}
 
Example 18
Source File: FormulaExecution.java    From domino-jna with Apache License 2.0 4 votes vote down vote up
private List<Object> parseFormulaResult(Pointer valuePtr, int valueLength) {
	short dataType = valuePtr.getShort(0);
	int dataTypeAsInt = (int) (dataType & 0xffff);
	
	boolean supportedType = false;
	if (dataTypeAsInt == NotesItem.TYPE_TEXT) {
		supportedType = true;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_TEXT_LIST) {
		supportedType = true;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_NUMBER) {
		supportedType = true;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_TIME) {
		supportedType = true;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_NUMBER_RANGE) {
		supportedType = true;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_TIME_RANGE) {
		supportedType = true;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_UNAVAILABLE) {
		supportedType = true;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_ERROR) {
		supportedType = true;
	}
	
	if (!supportedType) {
		throw new UnsupportedItemValueError("Data type is currently unsupported: "+dataTypeAsInt);
	}

	int checkDataType = valuePtr.getShort(0) & 0xffff;
	Pointer valueDataPtr = valuePtr.share(2);
	int valueDataLength = valueLength - 2;
	
	if (checkDataType!=dataTypeAsInt) {
		throw new IllegalStateException("Value data type does not meet expected date type: found "+checkDataType+", expected "+dataTypeAsInt);
	}
	if (dataTypeAsInt == NotesItem.TYPE_TEXT) {
		String txtVal = (String) ItemDecoder.decodeTextValue(valueDataPtr, valueDataLength, false);
		return txtVal==null ? Collections.emptyList() : Arrays.asList((Object) txtVal);
	}
	else if (dataTypeAsInt == NotesItem.TYPE_TEXT_LIST) {
		List<Object> textList = valueDataLength==0 ? Collections.emptyList() : ItemDecoder.decodeTextListValue(valueDataPtr, false);
		return textList==null ? Collections.emptyList() : textList;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_NUMBER) {
		double numVal = ItemDecoder.decodeNumber(valueDataPtr, valueDataLength);
		return Arrays.asList((Object) Double.valueOf(numVal));
	}
	else if (dataTypeAsInt == NotesItem.TYPE_NUMBER_RANGE) {
		List<Object> numberList = ItemDecoder.decodeNumberList(valueDataPtr, valueDataLength);
		return numberList==null ? Collections.emptyList() : numberList;
	}
	else if (dataTypeAsInt == NotesItem.TYPE_TIME) {
		if (isPreferNotesTimeDates()) {
			NotesTimeDate td = ItemDecoder.decodeTimeDateAsNotesTimeDate(valueDataPtr, valueDataLength);
			return td==null ? Collections.emptyList() : Arrays.asList((Object) td);
		}
		else {
			Calendar cal = ItemDecoder.decodeTimeDate(valueDataPtr, valueDataLength);
			return cal==null ? Collections.emptyList() : Arrays.asList((Object) cal);
			
		}
	}
	else if (dataTypeAsInt == NotesItem.TYPE_TIME_RANGE) {
		if (isPreferNotesTimeDates()) {
			List<Object> tdValues = ItemDecoder.decodeTimeDateListAsNotesTimeDate(valueDataPtr);
			return tdValues==null ? Collections.emptyList() : tdValues;
		}
		else {
			List<Object> calendarValues = ItemDecoder.decodeTimeDateList(valueDataPtr);
			return calendarValues==null ? Collections.emptyList() : calendarValues;
		}
	}
	else if (dataTypeAsInt == NotesItem.TYPE_UNAVAILABLE) {
		//e.g. returned by formula "@DeleteDocument"
		return Collections.emptyList();
	}
	else if (dataTypeAsInt == NotesItem.TYPE_ERROR) {
		//TODO find a way to parse error details
		throw new NotesError(0, "Could not evaluate formula: "+m_formula);
	}
	else {
		throw new UnsupportedItemValueError("Data is currently unsupported: "+dataTypeAsInt);
	}
}