DCOM: Proxy Disconnect

Robert Shearman rob at codeweavers.com
Wed Jul 28 13:22:56 CDT 2004


Changelog:

Mike Hearn <mh at codeweavers.com>
Implement disconnect for proxies so that stubs are properly destroyed.

-------------- next part --------------
Index: wine/dlls/ole32/compobj_private.h
===================================================================
RCS file: /home/wine/wine/dlls/ole32/compobj_private.h,v
retrieving revision 1.14
diff -u -r1.14 compobj_private.h
--- wine/dlls/ole32/compobj_private.h	22 Jul 2004 23:44:54 -0000	1.14
+++ wine/dlls/ole32/compobj_private.h	28 Jul 2004 13:43:47 -0000
@@ -147,6 +147,7 @@
 }
 
 HRESULT MARSHAL_Find_Stub_Buffer(wine_marshal_id *mid,IRpcStubBuffer **stub);
+void    MARSHAL_Invalidate_Stub_From_MID(wine_marshal_id *mid);
 
 HRESULT MARSHAL_GetStandardMarshalCF(LPVOID *ppv);
 
Index: wine/dlls/ole32/marshal.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/marshal.c,v
retrieving revision 1.23
diff -u -r1.23 marshal.c
--- wine/dlls/ole32/marshal.c	23 Jul 2004 19:10:13 -0000	1.23
+++ wine/dlls/ole32/marshal.c	28 Jul 2004 13:43:47 -0000
@@ -91,6 +91,21 @@
 static mid2unknown *proxies = NULL;
 static int nrofproxies = 0;
 
+void MARSHAL_Invalidate_Stub_From_MID(wine_marshal_id *mid) {
+    int i;
+
+    for (i=0;i<nrofstubs;i++) {
+        if (!stubs[i].valid) continue;
+        
+	if (MARSHAL_Compare_Mids(mid,&(stubs[i].mid))) {
+            stubs[i].valid = FALSE;
+	    return;
+	}
+    }
+    
+    return;
+}
+
 HRESULT
 MARSHAL_Find_Stub_Server(wine_marshal_id *mid,LPUNKNOWN *punk) {
     int i;
Index: wine/dlls/ole32/rpc.c
===================================================================
RCS file: /home/wine/wine/dlls/ole32/rpc.c,v
retrieving revision 1.19
diff -u -r1.19 rpc.c
--- wine/dlls/ole32/rpc.c	23 Jul 2004 22:58:13 -0000	1.19
+++ wine/dlls/ole32/rpc.c	28 Jul 2004 13:43:48 -0000
@@ -65,6 +65,14 @@
     DWORD		retval;
 } wine_rpc_response_header;
 
+/* used when shutting down a pipe, e.g. at the end of a process */
+#define REQTYPE_DISCONNECT	2
+typedef struct _wine_rpc_disconnect_header {
+  DWORD reqid;
+  wine_marshal_id mid; /* mid of stub to delete */
+} wine_rpc_disconnect_header;
+
+
 #define REQSTATE_START			0
 #define REQSTATE_REQ_QUEUED		1
 #define REQSTATE_REQ_WAITING_FOR_REPLY	2
@@ -284,10 +292,25 @@
 static ULONG WINAPI
 PipeBuf_Release(LPRPCCHANNELBUFFER iface) {
     ICOM_THIS(PipeBuf,iface);
+    wine_rpc_disconnect_header header;
+    HANDLE pipe;
+    DWORD reqtype = REQTYPE_DISCONNECT;
+
     This->ref--;
     if (This->ref)
 	return This->ref;
-    ERR("Free all stuff.\n");
+
+    FIXME("Free all stuff\n");
+
+    memcpy(&header.mid, &This->mid, sizeof(wine_marshal_id));
+
+    pipe = PIPE_FindByMID(&This->mid);
+
+    _xwrite(pipe, &reqtype, sizeof(reqtype));
+    _xwrite(pipe, &header, sizeof(wine_rpc_disconnect_header));
+
+    TRACE("written disconnect packet\n");
+
     HeapFree(GetProcessHeap(),0,This);
     return 0;
 }
@@ -629,7 +655,35 @@
     EnterCriticalSection(&(xpipe->crit));
     /*FIXME("%lx got reqtype %ld\n",GetCurrentProcessId(),reqtype);*/
 
-    if (reqtype == REQTYPE_REQUEST) {
+    if (reqtype == REQTYPE_DISCONNECT) { /* only received by servers */
+        wine_rpc_disconnect_header header;
+        IRpcStubBuffer *stub;
+        ULONG ret;
+
+        hres = _xread(xhPipe, &header, sizeof(header));
+        if (hres) {
+            ERR("could not read disconnect header\n");
+            goto end;
+        }
+
+        TRACE("read disconnect header\n");
+
+        hres = MARSHAL_Find_Stub_Buffer(&header.mid, &stub);
+        if (hres) {
+            ERR("could not locate stub to disconnect, mid.objectid=%p\n", (void*)header.mid.objectid);
+            goto end;
+        }
+
+
+        /* release reference added by MARSHAL_Find_Stub_Buffer call */
+        IRpcStubBuffer_Release(stub);
+        /* release it for real */
+        ret = IRpcStubBuffer_Release(stub);
+        /* FIXME: race */
+        if (ret == 0)
+            MARSHAL_Invalidate_Stub_From_MID(&header.mid);
+        goto end;
+    } else if (reqtype == REQTYPE_REQUEST) {
 	wine_rpc_request	*xreq;
 	RPC_GetRequest(&xreq);
 	xreq->hPipe = xhPipe;
@@ -641,8 +695,7 @@
 	if (hres) goto end;
 	xreq->state = REQSTATE_REQ_GOT;
 	goto end;
-    }
-    if (reqtype == REQTYPE_RESPONSE) {
+    } else if (reqtype == REQTYPE_RESPONSE) {
 	wine_rpc_response_header	resph;
 	int i;
 


More information about the wine-patches mailing list