Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-winehq
Project
Project
Details
Activity
Cycle Analytics
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Charts
Issues
0
Issues
0
List
Board
Labels
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Charts
Registry
Registry
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Charts
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
wine
wine-winehq
Commits
2b747d4e
Commit
2b747d4e
authored
Dec 27, 2004
by
Robert Shearman
Committed by
Alexandre Julliard
Dec 27, 2004
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
Implement COM local servers using table marshaling to avoid doing the
marshaling in a child thread where COM has not been initialized.
parent
5475a2e6
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
129 additions
and
114 deletions
+129
-114
compobj.c
dlls/ole32/compobj.c
+41
-114
compobj_private.h
dlls/ole32/compobj_private.h
+1
-0
rpc.c
dlls/ole32/rpc.c
+87
-0
No files found.
dlls/ole32/compobj.c
View file @
2b747d4e
...
...
@@ -101,8 +101,7 @@ typedef struct tagRegisteredClass
DWORD
runContext
;
DWORD
connectFlags
;
DWORD
dwCookie
;
HANDLE
hThread
;
/* only for localserver */
APARTMENT
*
apt
;
/* owning apartment */
LPSTREAM
pMarshaledData
;
/* FIXME: only really need to store OXID and IPID */
struct
tagRegisteredClass
*
nextClass
;
}
RegisteredClass
;
...
...
@@ -1101,116 +1100,12 @@ end:
return
hr
;
}
static
DWORD
WINAPI
_LocalServerThread
(
LPVOID
param
)
{
HANDLE
hPipe
;
char
pipefn
[
200
];
RegisteredClass
*
newClass
=
(
RegisteredClass
*
)
param
;
HRESULT
hres
;
IStream
*
pStm
;
STATSTG
ststg
;
unsigned
char
*
buffer
;
int
buflen
;
IClassFactory
*
classfac
;
LARGE_INTEGER
seekto
;
ULARGE_INTEGER
newpos
;
ULONG
res
;
TRACE
(
"Starting classfactory server thread for %s.
\n
"
,
debugstr_guid
(
&
newClass
->
classIdentifier
));
/* we need to enter the apartment of the thread which registered
* the class object to perform the next stage
*/
assert
(
newClass
->
apt
);
NtCurrentTeb
()
->
ReservedForOle
=
newClass
->
apt
;
strcpy
(
pipefn
,
PIPEPREF
);
WINE_StringFromCLSID
(
&
newClass
->
classIdentifier
,
pipefn
+
strlen
(
PIPEPREF
));
hPipe
=
CreateNamedPipeA
(
pipefn
,
PIPE_ACCESS_DUPLEX
,
PIPE_TYPE_BYTE
|
PIPE_WAIT
,
PIPE_UNLIMITED_INSTANCES
,
4096
,
4096
,
NMPWAIT_USE_DEFAULT_WAIT
,
NULL
);
if
(
hPipe
==
INVALID_HANDLE_VALUE
)
{
FIXME
(
"pipe creation failed for %s, le is %lx
\n
"
,
pipefn
,
GetLastError
());
return
1
;
}
while
(
1
)
{
if
(
!
ConnectNamedPipe
(
hPipe
,
NULL
))
{
ERR
(
"Failure during ConnectNamedPipe %lx, ABORT!
\n
"
,
GetLastError
());
break
;
}
TRACE
(
"marshalling IClassFactory to client
\n
"
);
hres
=
IUnknown_QueryInterface
(
newClass
->
classObject
,
&
IID_IClassFactory
,(
LPVOID
*
)
&
classfac
);
if
(
hres
)
return
hres
;
hres
=
CreateStreamOnHGlobal
(
0
,
TRUE
,
&
pStm
);
if
(
hres
)
{
FIXME
(
"Failed to create stream on hglobal.
\n
"
);
return
hres
;
}
hres
=
CoMarshalInterface
(
pStm
,
&
IID_IClassFactory
,(
LPVOID
)
classfac
,
0
,
NULL
,
0
);
if
(
hres
)
{
FIXME
(
"CoMarshalInterface failed, %lx!
\n
"
,
hres
);
return
hres
;
}
IUnknown_Release
(
classfac
);
/* is this right? */
hres
=
IStream_Stat
(
pStm
,
&
ststg
,
0
);
if
(
hres
)
return
hres
;
buflen
=
ststg
.
cbSize
.
u
.
LowPart
;
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
buflen
);
seekto
.
u
.
LowPart
=
0
;
seekto
.
u
.
HighPart
=
0
;
hres
=
IStream_Seek
(
pStm
,
seekto
,
SEEK_SET
,
&
newpos
);
if
(
hres
)
{
FIXME
(
"IStream_Seek failed, %lx
\n
"
,
hres
);
return
hres
;
}
hres
=
IStream_Read
(
pStm
,
buffer
,
buflen
,
&
res
);
if
(
hres
)
{
FIXME
(
"Stream Read failed, %lx
\n
"
,
hres
);
return
hres
;
}
IStream_Release
(
pStm
);
WriteFile
(
hPipe
,
buffer
,
buflen
,
&
res
,
NULL
);
FlushFileBuffers
(
hPipe
);
DisconnectNamedPipe
(
hPipe
);
TRACE
(
"done marshalling IClassFactory
\n
"
);
}
CloseHandle
(
hPipe
);
return
0
;
}
/******************************************************************************
* CoRegisterClassObject [OLE32.@]
*
* This method will register the class object for a given class
* ID. Servers housed in EXE files use this method instead of
* exporting DllGetClassObject to allow other code to connect to their
* objects.
*
* When a class object (an object which implements IClassFactory) is
* registered in this way, a new thread is started which listens for
* connections on a named pipe specific to the registered CLSID. When
* something else connects to it, it writes out the marshalled
* IClassFactory interface to the pipe. The code on the other end uses
* this buffer to unmarshal the class factory, and can then call
* methods on it.
*
* In Windows, such objects are registered with the RPC endpoint
* mapper, not with a unique named pipe.
*
* MSDN claims that multiple interface registrations are legal, but we
* can't do that with our current implementation.
* Registers the class object for a given class ID. Servers housed in EXE
* files use this method instead of exporting DllGetClassObject to allow
* other code to connect to their objects.
*
* RETURNS
* S_OK on success,
...
...
@@ -1219,6 +1114,10 @@ _LocalServerThread(LPVOID param) {
*
* SEE ALSO
* CoRevokeClassObject, CoGetClassObject
*
* BUGS
* MSDN claims that multiple interface registrations are legal, but we
* can't do that with our current implementation.
*/
HRESULT
WINAPI
CoRegisterClassObject
(
REFCLSID
rclsid
,
/* [in] CLSID of the object to register */
...
...
@@ -1264,10 +1163,9 @@ HRESULT WINAPI CoRegisterClassObject(
newClass
->
classIdentifier
=
*
rclsid
;
newClass
->
runContext
=
dwClsContext
;
newClass
->
connectFlags
=
flags
;
newClass
->
apt
=
COM_CurrentApt
();
/*
* Use the address of the chain node as the cookie since we are sure it's
* unique.
* unique.
FIXME: not on 64-bit platforms.
*/
newClass
->
dwCookie
=
(
DWORD
)
newClass
;
newClass
->
nextClass
=
firstRegisteredClass
;
...
...
@@ -1285,10 +1183,30 @@ HRESULT WINAPI CoRegisterClassObject(
*
lpdwRegister
=
newClass
->
dwCookie
;
if
(
dwClsContext
&
CLSCTX_LOCAL_SERVER
)
{
DWORD
tid
;
IClassFactory
*
classfac
;
hr
=
IUnknown_QueryInterface
(
newClass
->
classObject
,
&
IID_IClassFactory
,
(
LPVOID
*
)
&
classfac
);
if
(
hr
)
return
hr
;
hr
=
CreateStreamOnHGlobal
(
0
,
TRUE
,
&
newClass
->
pMarshaledData
);
if
(
hr
)
{
FIXME
(
"Failed to create stream on hglobal, %lx
\n
"
,
hr
);
IUnknown_Release
(
classfac
);
return
hr
;
}
hr
=
CoMarshalInterface
(
newClass
->
pMarshaledData
,
&
IID_IClassFactory
,
(
LPVOID
)
classfac
,
MSHCTX_LOCAL
,
NULL
,
MSHLFLAGS_TABLESTRONG
);
if
(
hr
)
{
FIXME
(
"CoMarshalInterface failed, %lx!
\n
"
,
hr
);
IUnknown_Release
(
classfac
);
return
hr
;
}
IUnknown_Release
(
classfac
);
start_apartment_listener_thread
();
newClass
->
hThread
=
CreateThread
(
NULL
,
0
,
_LocalServerThread
,
newClass
,
0
,
&
tid
);
RPC_StartLocalServer
(
&
newClass
->
classIdentifier
,
newClass
->
pMarshaledData
);
}
return
S_OK
;
}
...
...
@@ -1334,6 +1252,15 @@ HRESULT WINAPI CoRevokeClassObject(
*/
IUnknown_Release
(
curClass
->
classObject
);
if
(
curClass
->
pMarshaledData
)
{
LARGE_INTEGER
zero
;
memset
(
&
zero
,
0
,
sizeof
(
zero
));
/* FIXME: stop local server thread */
IStream_Seek
(
curClass
->
pMarshaledData
,
zero
,
SEEK_SET
,
NULL
);
CoReleaseMarshalData
(
curClass
->
pMarshaledData
);
}
/*
* Free the memory used by the chain node.
*/
...
...
dlls/ole32/compobj_private.h
View file @
2b747d4e
...
...
@@ -194,6 +194,7 @@ IRpcStubBuffer *mid_to_stubbuffer(wine_marshal_id *mid);
void
start_apartment_listener_thread
(
void
);
extern
HRESULT
PIPE_GetNewPipeBuf
(
wine_marshal_id
*
mid
,
IRpcChannelBuffer
**
pipebuf
);
void
RPC_StartLocalServer
(
REFCLSID
clsid
,
IStream
*
stream
);
/* This function initialize the Running Object Table */
HRESULT
WINAPI
RunningObjectTableImpl_Initialize
(
void
);
...
...
dlls/ole32/rpc.c
View file @
2b747d4e
...
...
@@ -829,3 +829,90 @@ void start_apartment_listener_thread()
CreateThread
(
NULL
,
0
,
apartment_listener_thread
,
apt
,
0
,
&
apt
->
listenertid
);
}
}
struct
local_server_params
{
CLSID
clsid
;
IStream
*
stream
;
};
static
DWORD
WINAPI
local_server_thread
(
LPVOID
param
)
{
struct
local_server_params
*
lsp
=
(
struct
local_server_params
*
)
param
;
HANDLE
hPipe
;
char
pipefn
[
200
];
HRESULT
hres
;
IStream
*
pStm
=
lsp
->
stream
;
STATSTG
ststg
;
unsigned
char
*
buffer
;
int
buflen
;
LARGE_INTEGER
seekto
;
ULARGE_INTEGER
newpos
;
ULONG
res
;
TRACE
(
"Starting threader for %s.
\n
"
,
debugstr_guid
(
&
lsp
->
clsid
));
strcpy
(
pipefn
,
PIPEPREF
);
WINE_StringFromCLSID
(
&
lsp
->
clsid
,
pipefn
+
strlen
(
PIPEPREF
));
HeapFree
(
GetProcessHeap
(),
0
,
lsp
);
hPipe
=
CreateNamedPipeA
(
pipefn
,
PIPE_ACCESS_DUPLEX
,
PIPE_TYPE_BYTE
|
PIPE_WAIT
,
PIPE_UNLIMITED_INSTANCES
,
4096
,
4096
,
NMPWAIT_USE_DEFAULT_WAIT
,
NULL
);
if
(
hPipe
==
INVALID_HANDLE_VALUE
)
{
FIXME
(
"pipe creation failed for %s, le is %ld
\n
"
,
pipefn
,
GetLastError
());
return
1
;
}
while
(
1
)
{
if
(
!
ConnectNamedPipe
(
hPipe
,
NULL
))
{
ERR
(
"Failure during ConnectNamedPipe %ld, ABORT!
\n
"
,
GetLastError
());
break
;
}
TRACE
(
"marshalling IClassFactory to client
\n
"
);
hres
=
IStream_Stat
(
pStm
,
&
ststg
,
0
);
if
(
hres
)
return
hres
;
buflen
=
ststg
.
cbSize
.
u
.
LowPart
;
buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
buflen
);
seekto
.
u
.
LowPart
=
0
;
seekto
.
u
.
HighPart
=
0
;
hres
=
IStream_Seek
(
pStm
,
seekto
,
SEEK_SET
,
&
newpos
);
if
(
hres
)
{
FIXME
(
"IStream_Seek failed, %lx
\n
"
,
hres
);
return
hres
;
}
hres
=
IStream_Read
(
pStm
,
buffer
,
buflen
,
&
res
);
if
(
hres
)
{
FIXME
(
"Stream Read failed, %lx
\n
"
,
hres
);
return
hres
;
}
IStream_Release
(
pStm
);
WriteFile
(
hPipe
,
buffer
,
buflen
,
&
res
,
NULL
);
FlushFileBuffers
(
hPipe
);
DisconnectNamedPipe
(
hPipe
);
TRACE
(
"done marshalling IClassFactory
\n
"
);
}
CloseHandle
(
hPipe
);
return
0
;
}
void
RPC_StartLocalServer
(
REFCLSID
clsid
,
IStream
*
stream
)
{
DWORD
tid
;
HANDLE
thread
;
struct
local_server_params
*
lsp
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
*
lsp
));
lsp
->
clsid
=
*
clsid
;
lsp
->
stream
=
stream
;
thread
=
CreateThread
(
NULL
,
0
,
local_server_thread
,
lsp
,
0
,
&
tid
);
CloseHandle
(
thread
);
/* FIXME: failure handling */
}
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment