diff --git a/basis/windows/advapi32/advapi32.factor b/basis/windows/advapi32/advapi32.factor
old mode 100644
new mode 100755
index 6e040871f8..6d80534e8c
--- a/basis/windows/advapi32/advapi32.factor
+++ b/basis/windows/advapi32/advapi32.factor
@@ -1,4 +1,5 @@
-USING: alien.syntax kernel math windows.types math.bitwise ;
+USING: alien.syntax kernel math windows.types windows.kernel32
+math.bitwise ;
 IN: windows.advapi32
 
 LIBRARY: advapi32
diff --git a/vm/callstack.cpp b/vm/callstack.cpp
index 608a5c39e5..39988ae976 100755
--- a/vm/callstack.cpp
+++ b/vm/callstack.cpp
@@ -107,41 +107,43 @@ stack_frame *frame_successor(stack_frame *frame)
 /* Allocates memory */
 cell frame_scan(stack_frame *frame)
 {
-	if(frame_type(frame) == QUOTATION_TYPE)
+	switch(frame_type(frame))
 	{
-		cell quot = frame_executing(frame);
-		if(quot == F)
-			return F;
-		else
+	case QUOTATION_TYPE:
 		{
-			char *return_addr = (char *)FRAME_RETURN_ADDRESS(frame);
-			char *quot_xt = (char *)(frame_code(frame) + 1);
+			cell quot = frame_executing(frame);
+			if(quot == F)
+				return F;
+			else
+			{
+				char *return_addr = (char *)FRAME_RETURN_ADDRESS(frame);
+				char *quot_xt = (char *)(frame_code(frame) + 1);
 
-			return tag_fixnum(quot_code_offset_to_scan(
-				quot,(cell)(return_addr - quot_xt)));
+				return tag_fixnum(quot_code_offset_to_scan(
+					quot,(cell)(return_addr - quot_xt)));
+			}
 		}
-	}
-	else
+	case WORD_TYPE:
 		return F;
+	default:
+		critical_error("Bad frame type",frame_type(frame));
+		return F;
+	}
 }
 
 namespace
 {
 
-struct stack_frame_counter {
-	cell count;
-	stack_frame_counter() : count(0) {}
-	void operator()(stack_frame *frame) { count += 2; }
-};
-
 struct stack_frame_accumulator {
-	cell index;
-	gc_root<array> frames;
-	stack_frame_accumulator(cell count) : index(0), frames(allot_array(count,F)) {}
+	growable_array frames;
+
 	void operator()(stack_frame *frame)
 	{
-		set_array_nth(frames.untagged(),index++,frame_executing(frame));
-		set_array_nth(frames.untagged(),index++,frame_scan(frame));
+		gc_root<object> executing(frame_executing(frame));
+		gc_root<object> scan(frame_scan(frame));
+
+		frames.add(executing.value());
+		frames.add(scan.value());
 	}
 };
 
@@ -151,13 +153,11 @@ PRIMITIVE(callstack_to_array)
 {
 	gc_root<callstack> callstack(dpop());
 
-	stack_frame_counter counter;
-	iterate_callstack_object(callstack.untagged(),counter);
-
-	stack_frame_accumulator accum(counter.count);
+	stack_frame_accumulator accum;
 	iterate_callstack_object(callstack.untagged(),accum);
+	accum.frames.trim();
 
-	dpush(accum.frames.value());
+	dpush(accum.frames.elements.value());
 }
 
 stack_frame *innermost_stack_frame(callstack *stack)
diff --git a/vm/callstack.hpp b/vm/callstack.hpp
index d92e5f69e0..a3cc058e2b 100755
--- a/vm/callstack.hpp
+++ b/vm/callstack.hpp
@@ -33,9 +33,19 @@ template<typename T> void iterate_callstack(cell top, cell bottom, T &iterator)
 	}
 }
 
-template<typename T> void iterate_callstack_object(callstack *stack, T &iterator)
+/* This is a little tricky. The iterator may allocate memory, so we
+keep the callstack in a GC root and use relative offsets */
+template<typename T> void iterate_callstack_object(callstack *stack_, T &iterator)
 {
-	iterate_callstack((cell)stack->top(),(cell)stack->bottom(),iterator);
+	gc_root<callstack> stack(stack_);
+	fixnum frame_offset = untag_fixnum(stack->length) - sizeof(stack_frame);
+
+	while(frame_offset >= 0)
+	{
+		stack_frame *frame = stack->frame_at(frame_offset);
+		frame_offset -= frame->size;
+		iterator(frame);
+	}
 }
 
 }
diff --git a/vm/layouts.hpp b/vm/layouts.hpp
index 3fe89cb558..7736143c50 100755
--- a/vm/layouts.hpp
+++ b/vm/layouts.hpp
@@ -309,6 +309,11 @@ struct callstack : public object {
 	/* tagged */
 	cell length;
 	
+	stack_frame *frame_at(cell offset)
+	{
+		return (stack_frame *)((char *)(this + 1) + offset);
+	}
+
 	stack_frame *top() { return (stack_frame *)(this + 1); }
 	stack_frame *bottom() { return (stack_frame *)((cell)(this + 1) + untag_fixnum(length)); }
 };