diff --git a/Changelog.md b/Changelog.md
index b7d2363..40c1642 100644
--- a/Changelog.md
+++ b/Changelog.md
@@ -4,6 +4,9 @@
 * Adds `types::Value` for dynamic column types.
 * Adds support for user-defined aggregate functions (behind the existing `functions` Cargo feature).
 * Introduces a `RowIndex` trait allowing columns to be fetched via index (as before) or name (new).
+* Introduces `ZeroBlob` type under the `blob` module/feature exposing SQLite's zeroblob API.
+* Adds CI testing for Windows via AppVeyor.
+* Fixes a warning building libsqlite3-sys under Rust 1.6.
 
 # Version 0.6.0 (2015-12-17)
 
diff --git a/README.md b/README.md
index a813174..bc56bc3 100644
--- a/README.md
+++ b/README.md
@@ -1,6 +1,7 @@
 # Rusqlite
 
-[![Build Status](https://api.travis-ci.org/jgallagher/rusqlite.svg?branch=master)](https://travis-ci.org/jgallagher/rusqlite)
+[![Travis Build Status](https://api.travis-ci.org/jgallagher/rusqlite.svg?branch=master)](https://travis-ci.org/jgallagher/rusqlite)
+[![AppVeyor Build Status](https://ci.appveyor.com/api/projects/status/github/jgallagher/rusqlite?branch=master&svg=true)](https://ci.appveyor.com/project/jgallagher/rusqlite)
 
 Rusqlite is an ergonomic wrapper for using SQLite from Rust. It attempts to expose
 an interface similar to [rust-postgres](https://github.com/sfackler/rust-postgres). View the full
diff --git a/appveyor.yml b/appveyor.yml
new file mode 100644
index 0000000..9fb260e
--- /dev/null
+++ b/appveyor.yml
@@ -0,0 +1,22 @@
+environment:
+  TARGET: 1.6.0-x86_64-pc-windows-gnu
+  MSYS2_BITS: 64
+install:
+  - ps: Start-FileDownload "https://static.rust-lang.org/dist/rust-${env:TARGET}.exe"
+  - rust-%TARGET%.exe /VERYSILENT /NORESTART /DIR="C:\Program Files (x86)\Rust"
+  - SET PATH=%PATH%;C:\Program Files (x86)\Rust\bin
+  - if defined MSYS2_BITS set PATH=%PATH%;C:\msys64\mingw%MSYS2_BITS%\bin
+  - rustc -V
+  - cargo -V
+  - ps: Start-FileDownload 'http://sqlite.org/2016/sqlite-dll-win64-x64-3100200.zip'
+  - cmd: 7z e sqlite-dll-win64-x64-3100200.zip -y > nul
+  - SET SQLITE3_LIB_DIR=%APPVEYOR_BUILD_FOLDER%
+
+build: false
+
+test_script:
+  - cargo test --lib --verbose
+  - cargo test --lib --features "backup blob functions load_extension trace"
+
+cache:
+  - C:\Users\appveyor\.cargo
diff --git a/libsqlite3-sys/src/bindgen.rs b/libsqlite3-sys/src/bindgen.rs
index a60be96..1b60335 100644
--- a/libsqlite3-sys/src/bindgen.rs
+++ b/libsqlite3-sys/src/bindgen.rs
@@ -1,4 +1,4 @@
-#![allow(raw_pointer_derive, non_snake_case, non_camel_case_types)]
+#![allow(non_snake_case, non_camel_case_types)]
 /* automatically generated by rust-bindgen */
 
 pub type va_list = __builtin_va_list;
diff --git a/src/blob.rs b/src/blob.rs
index a13f3e7..f8b1710 100644
--- a/src/blob.rs
+++ b/src/blob.rs
@@ -17,6 +17,7 @@
 //! extern crate rusqlite;
 //!
 //! use rusqlite::{Connection, DatabaseName};
+//! use rusqlite::blob::ZeroBlob;
 //! use std::io::{Read, Write, Seek, SeekFrom};
 //!
 //! fn main() {
@@ -38,7 +39,7 @@
 //!     let bytes_read = blob.read(&mut buf[..]).unwrap();
 //!     assert_eq!(bytes_read, 10); // note we read 10 bytes because the blob has size 10
 //!
-//!     db.execute("INSERT INTO test (content) VALUES (ZEROBLOB(64))", &[]).unwrap();
+//!     db.execute("INSERT INTO test (content) VALUES (?)", &[&ZeroBlob(64)]).unwrap();
 //!
 //!     // given a new row ID, we can reopen the blob on that row
 //!     let rowid = db.last_insert_rowid();
@@ -51,8 +52,10 @@ use std::io;
 use std::cmp::min;
 use std::mem;
 use std::ptr;
+use libc::c_int;
 
 use super::ffi;
+use super::types::ToSql;
 use {Result, Connection, DatabaseName};
 
 /// Handle to an open BLOB.
@@ -232,6 +235,19 @@ impl<'conn> Drop for Blob<'conn> {
     }
 }
 
+/// BLOB of length N that is filled with zeroes.
+/// Zeroblobs are intended to serve as placeholders for BLOBs whose content is later written using incremental BLOB I/O routines.
+/// A negative value for the zeroblob results in a zero-length BLOB.
+#[derive(Copy,Clone)]
+pub struct ZeroBlob(pub i32);
+
+impl ToSql for ZeroBlob {
+    unsafe fn bind_parameter(&self, stmt: *mut ffi::sqlite3_stmt, col: c_int) -> c_int {
+        let ZeroBlob(length) = *self;
+        ffi::sqlite3_bind_zeroblob(stmt, col, length)
+    }
+}
+
 #[cfg(test)]
 mod test {
     use std::io::{BufReader, BufRead, BufWriter, Read, Write, Seek, SeekFrom};
diff --git a/src/functions.rs b/src/functions.rs
index e4d4f9c..248cea5 100644
--- a/src/functions.rs
+++ b/src/functions.rs
@@ -509,9 +509,10 @@ impl InnerConnection {
         where D: Aggregate<A, T>,
               T: ToResult
     {
-        unsafe fn aggregate_context<A>(ctx: *mut sqlite3_context) -> Option<*mut *mut A> {
-            let pac = ffi::sqlite3_aggregate_context(ctx, ::std::mem::size_of::<*mut A>() as c_int)
-                            as *mut *mut A;
+        unsafe fn aggregate_context<A>(ctx: *mut sqlite3_context,
+                                       bytes: usize)
+                                       -> Option<*mut *mut A> {
+            let pac = ffi::sqlite3_aggregate_context(ctx, bytes as c_int) as *mut *mut A;
             if pac.is_null() {
                 return None;
             }
@@ -545,7 +546,7 @@ impl InnerConnection {
             assert!(!boxed_aggr.is_null(),
                     "Internal error - null aggregate pointer");
 
-            let pac = match aggregate_context(ctx) {
+            let pac = match aggregate_context(ctx, ::std::mem::size_of::<*mut A>()) {
                 Some(pac) => pac,
                 None => {
                     ffi::sqlite3_result_error_nomem(ctx);
@@ -576,19 +577,18 @@ impl InnerConnection {
             assert!(!boxed_aggr.is_null(),
                     "Internal error - null aggregate pointer");
 
-            let pac = match aggregate_context(ctx) {
-                Some(pac) => pac,
-                None => {
-                    ffi::sqlite3_result_error_nomem(ctx);
-                    return;
+            // Within the xFinal callback, it is customary to set N=0 in calls to
+            // sqlite3_aggregate_context(C,N) so that no pointless memory allocations occur.
+            let a: Option<A> = match aggregate_context(ctx, 0) {
+                Some(pac) => {
+                    if (*pac).is_null() {
+                        None
+                    } else {
+                        let a = Box::from_raw(*pac);
+                        Some(*a)
+                    }
                 }
-            };
-
-            let a: Option<A> = if (*pac).is_null() {
-                None
-            } else {
-                let a = Box::from_raw(*pac);
-                Some(*a)
+                None => None,
             };
 
             match (*boxed_aggr).finalize(a) {