diff --git a/go.mod b/go.mod
index eaf11e0..b4e3a84 100644
--- a/go.mod
+++ b/go.mod
@@ -6,4 +6,5 @@ require (
 	github.com/digitalocean/go-libvirt v0.0.0-20201209184759-e2a69bcd5bd1
 	github.com/fatih/camelcase v1.0.0
 	golang.org/x/sys v0.0.0-20210119212857-b64e53b001e4
+	gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce
 )
diff --git a/go.sum b/go.sum
index d8290aa..1c51165 100644
--- a/go.sum
+++ b/go.sum
@@ -36,5 +36,7 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543 h1:E7g+9GITq07hpfrRu66IV
 golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405 h1:yhCVgyC4o1eVCa2tZl7eS0r+SDo693bJlVdllGtEeKM=
 gopkg.in/check.v1 v0.0.0-20161208181325-20d25e280405/go.mod h1:Co6ibVJAznAaIkqp8huTwlJQCZ016jof/cbN4VW5Yz0=
+gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce h1:+JknDZhAj8YMt7GC73Ei8pv4MzjDUNPHgQWJdtMAaDU=
+gopkg.in/natefinch/npipe.v2 v2.0.0-20160621034901-c1b8fa8bdcce/go.mod h1:5AcXVHNjg+BDxry382+8OKon8SEWiKktQR07RKPsv1c=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c h1:dUUwHk2QECo/6vqA44rthZ8ie2QXMNeKRTHCNY2nXvo=
 gopkg.in/yaml.v3 v3.0.0-20200313102051-9f266ea9e77c/go.mod h1:K4uyk7z7BCEPqu6E+C64Yfv1cQ7kz7rIZviUmN+EgEM=
diff --git a/qmp/README.md b/qmp/README.md
index 729280b..c9ce7fd 100644
--- a/qmp/README.md
+++ b/qmp/README.md
@@ -35,6 +35,12 @@ If your QEMU instances are not managed by libvirt, direct communication over its
 monitor, err := qmp.NewSocketMonitor("unix", "/var/lib/qemu/example.monitor", 2*time.Second)
 ```
 
+The Windows version of QEMU doesn't have UNIX sockets, but instead uses named pipes (fifo) for communication.
+
+```go
+monitor, err := qmp.NewPipeMonitor("example", 2*time.Second) // will open `\\.\pipe\example`
+```
+
 ## Examples
 
 Using the above to establish a new `qmp.Monitor`, the following examples provide a brief overview of QMP usage.
diff --git a/qmp/socket_unix.go b/qmp/socket_unix.go
index 859ff64..ac2da66 100644
--- a/qmp/socket_unix.go
+++ b/qmp/socket_unix.go
@@ -17,11 +17,20 @@
 package qmp
 
 import (
+	"fmt"
 	"os"
+	"time"
 
 	"golang.org/x/sys/unix"
 )
 
+// NewPipeMonitor configures a connection to the provided QEMU monitor pipe.
+// An error is returned if the pipe cannot be successfully dialed, or the
+// dial attempt times out.
+func NewPipeMonitor(addr string, timeout time.Duration) (*SocketMonitor, error) {
+	return nil, fmt.Errorf("unimplemented")
+}
+
 func getUnixRights(file *os.File) []byte {
 	return unix.UnixRights(int(file.Fd()))
 }
diff --git a/qmp/socket_windows.go b/qmp/socket_windows.go
index b8a611d..7227062 100644
--- a/qmp/socket_windows.go
+++ b/qmp/socket_windows.go
@@ -18,8 +18,28 @@ package qmp
 
 import (
 	"os"
+	"time"
+
+	"gopkg.in/natefinch/npipe.v2"
 )
 
+// NewPipeMonitor configures a connection to the provided QEMU monitor pipe.
+// An error is returned if the pipe cannot be successfully dialed, or the
+// dial attempt times out.
+func NewPipeMonitor(addr string, timeout time.Duration) (*SocketMonitor, error) {
+        c, err := npipe.DialTimeout(addr, timeout)
+        if err != nil {
+                return nil, err
+        }
+
+        mon := &SocketMonitor{
+                c:         c,
+                listeners: new(int32),
+        }
+
+        return mon, nil
+}
+
 func getUnixRights(file *os.File) []byte {
 	return nil
 }