fixes for windows
diff --git a/src/core/iomgr/iocp_windows.c b/src/core/iomgr/iocp_windows.c
index 0799622..006f8b2 100644
--- a/src/core/iomgr/iocp_windows.c
+++ b/src/core/iomgr/iocp_windows.c
@@ -112,7 +112,6 @@
 static void iocp_loop(void *p) {
   while (gpr_atm_acq_load(&g_custom_events) || 
          !gpr_event_get(&g_shutdown_iocp)) {
-    grpc_maybe_call_delayed_callbacks(NULL, 1);
     do_iocp_work();
   }
 
diff --git a/src/core/iomgr/socket_windows.c b/src/core/iomgr/socket_windows.c
index dbc6463..2cbe945 100644
--- a/src/core/iomgr/socket_windows.c
+++ b/src/core/iomgr/socket_windows.c
@@ -63,11 +63,10 @@
    various callsites of that function, which happens to be in various
    mutex hold states, and that'd be unsafe to call them directly. */
 void grpc_winsocket_shutdown(grpc_winsocket *winsocket) {
-  shutdown(winsocket->socket, SD_BOTH);
+  closesocket(winsocket->socket);
 }
 
 void grpc_winsocket_destroy(grpc_winsocket *winsocket) {
-  closesocket(winsocket->socket);
   grpc_iomgr_unregister_object(&winsocket->iomgr_object);
   gpr_mu_destroy(&winsocket->state_mu);
   gpr_free(winsocket);
diff --git a/src/core/iomgr/tcp_server_windows.c b/src/core/iomgr/tcp_server_windows.c
index 21f19f0..b513d85 100644
--- a/src/core/iomgr/tcp_server_windows.c
+++ b/src/core/iomgr/tcp_server_windows.c
@@ -106,6 +106,22 @@
 
 static void dont_care_about_shutdown_completion(void *arg) {}
 
+static void finish_shutdown(grpc_tcp_server *s) {
+  size_t i;
+
+  s->shutdown_complete(s->shutdown_complete_arg);
+
+  /* Now that the accepts have been aborted, we can destroy the sockets.
+  The IOCP won't get notified on these, so we can flag them as already
+  closed by the system. */
+  for (i = 0; i < s->nports; i++) {
+    server_port *sp = &s->ports[i];
+    grpc_winsocket_destroy(sp->socket);
+  }
+  gpr_free(s->ports);
+  gpr_free(s);
+}
+
 /* Public function. Stops and destroys a grpc_tcp_server. */
 void grpc_tcp_server_destroy(grpc_tcp_server *s,
                              void (*shutdown_complete)(void *shutdown_done_arg),
@@ -131,18 +147,8 @@
   }
   gpr_mu_unlock(&s->mu);
 
-  /* Now that the accepts have been aborted, we can destroy the sockets.
-     The IOCP won't get notified on these, so we can flag them as already
-     closed by the system. */
-  for (i = 0; i < s->nports; i++) {
-    server_port *sp = &s->ports[i];
-    grpc_winsocket_destroy(sp->socket);
-  }
-  gpr_free(s->ports);
-  gpr_free(s);
-
   if (immediately_done) {
-    s->shutdown_complete(s->shutdown_complete_arg);
+    finish_shutdown(s);
   }
 }
 
@@ -195,18 +201,16 @@
 }
 
 static void decrement_active_ports_and_notify(server_port *sp) {
-  void(*notify)(void *) = NULL;
-  void *notify_arg = NULL;
+  int notify = 0;
   sp->shutting_down = 0;
   gpr_mu_lock(&sp->server->mu);
   GPR_ASSERT(sp->server->active_ports > 0);
-  if (0 == --sp->server->active_ports) {
-    notify = sp->server->shutdown_complete;
-    notify_arg = sp->server->shutdown_complete_arg;
+  if (0 == --sp->server->active_ports && sp->server->shutdown_complete != NULL) {
+    notify = 1;
   }
   gpr_mu_unlock(&sp->server->mu);
-  if (notify != NULL) {
-    notify(notify_arg);
+  if (notify) {
+    finish_shutdown(sp->server);
   }
 }
 
diff --git a/src/core/transport/chttp2_transport.c b/src/core/transport/chttp2_transport.c
index aa7a7c9..b8705cc 100644
--- a/src/core/transport/chttp2_transport.c
+++ b/src/core/transport/chttp2_transport.c
@@ -1119,7 +1119,7 @@
   if (!*success || i != t->read_buffer.count) {
     drop_connection(t);
     read_error_locked(t);
-  } else {
+  } else if (!t->closed) {
     keep_reading = 1;
     prevent_endpoint_shutdown(t);
   }