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
def211c4
Commit
def211c4
authored
Feb 19, 2003
by
Ove Kaaven
Committed by
Alexandre Julliard
Feb 19, 2003
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
For better concurrency, separate the connections from the bindings.
parent
586808fd
Show whitespace changes
Inline
Side-by-side
Showing
5 changed files
with
561 additions
and
310 deletions
+561
-310
rpc_binding.c
dlls/rpcrt4/rpc_binding.c
+224
-162
rpc_binding.h
dlls/rpcrt4/rpc_binding.h
+24
-6
rpc_message.c
dlls/rpcrt4/rpc_message.c
+82
-25
rpc_server.c
dlls/rpcrt4/rpc_server.c
+230
-116
rpc_server.h
dlls/rpcrt4/rpc_server.h
+1
-1
No files found.
dlls/rpcrt4/rpc_binding.c
View file @
def211c4
...
...
@@ -93,13 +93,209 @@ void RPCRT4_strfree(LPSTR src)
if
(
src
)
HeapFree
(
GetProcessHeap
(),
0
,
src
);
}
RPC_STATUS
RPCRT4_CreateBindingA
(
RpcBinding
**
Binding
,
BOOL
server
,
LPSTR
Protseq
)
RPC_STATUS
RPCRT4_CreateConnection
(
RpcConnection
**
Connection
,
BOOL
server
,
LPSTR
Protseq
,
LPSTR
NetworkAddr
,
LPSTR
Endpoint
,
LPSTR
NetworkOptions
)
{
RpcConnection
*
NewConnection
;
NewConnection
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
RpcConnection
));
NewConnection
->
server
=
server
;
NewConnection
->
Protseq
=
RPCRT4_strdupA
(
Protseq
);
NewConnection
->
NetworkAddr
=
RPCRT4_strdupA
(
NetworkAddr
);
NewConnection
->
Endpoint
=
RPCRT4_strdupA
(
Endpoint
);
TRACE
(
"connection: %p
\n
"
,
NewConnection
);
*
Connection
=
NewConnection
;
return
RPC_S_OK
;
}
RPC_STATUS
RPCRT4_DestroyConnection
(
RpcConnection
*
Connection
)
{
TRACE
(
"connection: %p
\n
"
,
Connection
);
if
(
Connection
->
Used
)
ERR
(
"connection is still in use
\n
"
);
RPCRT4_CloseConnection
(
Connection
);
RPCRT4_strfree
(
Connection
->
Endpoint
);
RPCRT4_strfree
(
Connection
->
NetworkAddr
);
RPCRT4_strfree
(
Connection
->
Protseq
);
HeapFree
(
GetProcessHeap
(),
0
,
Connection
);
return
RPC_S_OK
;
}
RPC_STATUS
RPCRT4_OpenConnection
(
RpcConnection
*
Connection
)
{
TRACE
(
"(Connection == ^%p)
\n
"
,
Connection
);
if
(
!
Connection
->
conn
)
{
if
(
Connection
->
server
)
{
/* server */
/* protseq=ncalrpc: supposed to use NT LPC ports,
* but we'll implement it with named pipes for now */
if
(
strcmp
(
Connection
->
Protseq
,
"ncalrpc"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
.
\\
pipe
\\
lrpc
\\
"
;
LPSTR
pname
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Connection
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Connection
->
Endpoint
);
TRACE
(
"listening on %s
\n
"
,
pname
);
Connection
->
conn
=
CreateNamedPipeA
(
pname
,
PIPE_ACCESS_DUPLEX
|
FILE_FLAG_OVERLAPPED
,
0
,
PIPE_UNLIMITED_INSTANCES
,
0
,
0
,
5000
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Connection
->
ovl
,
0
,
sizeof
(
Connection
->
ovl
));
Connection
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
if
(
!
ConnectNamedPipe
(
Connection
->
conn
,
&
Connection
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
==
ERROR_PIPE_CONNECTED
)
{
SetEvent
(
Connection
->
ovl
.
hEvent
);
return
RPC_S_OK
;
}
return
err
;
}
}
/* protseq=ncacn_np: named pipes */
else
if
(
strcmp
(
Connection
->
Protseq
,
"ncacn_np"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
."
;
LPSTR
pname
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Connection
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Connection
->
Endpoint
);
TRACE
(
"listening on %s
\n
"
,
pname
);
Connection
->
conn
=
CreateNamedPipeA
(
pname
,
PIPE_ACCESS_DUPLEX
|
FILE_FLAG_OVERLAPPED
,
0
,
PIPE_UNLIMITED_INSTANCES
,
0
,
0
,
5000
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Connection
->
ovl
,
0
,
sizeof
(
Connection
->
ovl
));
Connection
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
if
(
!
ConnectNamedPipe
(
Connection
->
conn
,
&
Connection
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
==
ERROR_PIPE_CONNECTED
)
{
SetEvent
(
Connection
->
ovl
.
hEvent
);
return
RPC_S_OK
;
}
return
err
;
}
}
else
{
ERR
(
"protseq %s not supported
\n
"
,
Connection
->
Protseq
);
return
RPC_S_PROTSEQ_NOT_SUPPORTED
;
}
}
else
{
/* client */
/* protseq=ncalrpc: supposed to use NT LPC ports,
* but we'll implement it with named pipes for now */
if
(
strcmp
(
Connection
->
Protseq
,
"ncalrpc"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
.
\\
pipe
\\
lrpc
\\
"
;
LPSTR
pname
;
HANDLE
conn
;
DWORD
err
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Connection
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Connection
->
Endpoint
);
TRACE
(
"connecting to %s
\n
"
,
pname
);
while
(
TRUE
)
{
if
(
WaitNamedPipeA
(
pname
,
NMPWAIT_WAIT_FOREVER
))
{
conn
=
CreateFileA
(
pname
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_OVERLAPPED
,
0
);
if
(
conn
!=
INVALID_HANDLE_VALUE
)
break
;
err
=
GetLastError
();
if
(
err
==
ERROR_PIPE_BUSY
)
continue
;
TRACE
(
"connection failed, error=%lx
\n
"
,
err
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
return
err
;
}
else
{
err
=
GetLastError
();
TRACE
(
"connection failed, error=%lx
\n
"
,
err
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
return
err
;
}
}
/* success */
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Connection
->
ovl
,
0
,
sizeof
(
Connection
->
ovl
));
Connection
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
Connection
->
conn
=
conn
;
}
/* protseq=ncacn_np: named pipes */
else
if
(
strcmp
(
Connection
->
Protseq
,
"ncacn_np"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
."
;
LPSTR
pname
;
HANDLE
conn
;
DWORD
err
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Connection
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Connection
->
Endpoint
);
TRACE
(
"connecting to %s
\n
"
,
pname
);
conn
=
CreateFileA
(
pname
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_OVERLAPPED
,
0
);
if
(
conn
==
INVALID_HANDLE_VALUE
)
{
err
=
GetLastError
();
/* we don't need to handle ERROR_PIPE_BUSY here,
* the doc says that it is returned to the app */
TRACE
(
"connection failed, error=%lx
\n
"
,
err
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
return
err
;
}
/* success */
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Connection
->
ovl
,
0
,
sizeof
(
Connection
->
ovl
));
Connection
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
Connection
->
conn
=
conn
;
}
else
{
ERR
(
"protseq %s not supported
\n
"
,
Connection
->
Protseq
);
return
RPC_S_PROTSEQ_NOT_SUPPORTED
;
}
}
}
return
RPC_S_OK
;
}
RPC_STATUS
RPCRT4_CloseConnection
(
RpcConnection
*
Connection
)
{
TRACE
(
"(Connection == ^%p)
\n
"
,
Connection
);
if
(
Connection
->
conn
)
{
CancelIo
(
Connection
->
conn
);
CloseHandle
(
Connection
->
conn
);
Connection
->
conn
=
0
;
}
if
(
Connection
->
ovl
.
hEvent
)
{
CloseHandle
(
Connection
->
ovl
.
hEvent
);
Connection
->
ovl
.
hEvent
=
0
;
}
return
RPC_S_OK
;
}
RPC_STATUS
RPCRT4_SpawnConnection
(
RpcConnection
**
Connection
,
RpcConnection
*
OldConnection
)
{
RpcConnection
*
NewConnection
;
RPC_STATUS
err
=
RPCRT4_CreateConnection
(
&
NewConnection
,
OldConnection
->
server
,
OldConnection
->
Protseq
,
OldConnection
->
NetworkAddr
,
OldConnection
->
Endpoint
,
NULL
);
if
(
err
==
RPC_S_OK
)
{
/* because of the way named pipes work, we'll transfer the connected pipe
* to the child, then reopen the server binding to continue listening */
NewConnection
->
conn
=
OldConnection
->
conn
;
NewConnection
->
ovl
=
OldConnection
->
ovl
;
OldConnection
->
conn
=
0
;
memset
(
&
OldConnection
->
ovl
,
0
,
sizeof
(
OldConnection
->
ovl
));
*
Connection
=
NewConnection
;
RPCRT4_OpenConnection
(
OldConnection
);
}
return
err
;
}
RPC_STATUS
RPCRT4_AllocBinding
(
RpcBinding
**
Binding
,
BOOL
server
)
{
RpcBinding
*
NewBinding
;
NewBinding
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
RpcBinding
));
NewBinding
->
refs
=
1
;
NewBinding
->
server
=
server
;
*
Binding
=
NewBinding
;
return
RPC_S_OK
;
}
RPC_STATUS
RPCRT4_CreateBindingA
(
RpcBinding
**
Binding
,
BOOL
server
,
LPSTR
Protseq
)
{
RpcBinding
*
NewBinding
;
RPCRT4_AllocBinding
(
&
NewBinding
,
server
);
NewBinding
->
Protseq
=
RPCRT4_strdupA
(
Protseq
);
TRACE
(
"binding: %p
\n
"
,
NewBinding
);
...
...
@@ -111,16 +307,8 @@ RPC_STATUS RPCRT4_CreateBindingA(RpcBinding** Binding, BOOL server, LPSTR Protse
RPC_STATUS
RPCRT4_CreateBindingW
(
RpcBinding
**
Binding
,
BOOL
server
,
LPWSTR
Protseq
)
{
RpcBinding
*
NewBinding
;
if
(
Binding
)
TRACE
(
"(*Binding == ^%p, server == %s, Protseq ==
\"
%s
\"
)
\n
"
,
*
Binding
,
server
?
"Yes"
:
"No"
,
debugstr_w
(
Protseq
));
else
{
ERR
(
"!RpcBinding?
\n
"
);
assert
(
FALSE
);
/* we will crash below anyhow... */
}
NewBinding
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
RpcBinding
));
NewBinding
->
refs
=
1
;
NewBinding
->
server
=
server
;
RPCRT4_AllocBinding
(
&
NewBinding
,
server
);
NewBinding
->
Protseq
=
RPCRT4_strdupWtoA
(
Protseq
);
TRACE
(
"binding: %p
\n
"
,
NewBinding
);
...
...
@@ -131,8 +319,8 @@ RPC_STATUS RPCRT4_CreateBindingW(RpcBinding** Binding, BOOL server, LPWSTR Prots
RPC_STATUS
RPCRT4_CompleteBindingA
(
RpcBinding
*
Binding
,
LPSTR
NetworkAddr
,
LPSTR
Endpoint
,
LPSTR
NetworkOptions
)
{
TRACE
(
"(RpcBinding == ^%p, NetworkAddr ==
\"
%s
\"
, EndPoint ==
\"
%s
\"
, NetworkOptions ==
\"
%s
\"
)
\n
"
,
Binding
,
NetworkAddr
,
Endpoint
,
NetworkOptions
);
TRACE
(
"(RpcBinding == ^%p, NetworkAddr ==
\"
%s
\"
, EndPoint ==
\"
%s
\"
, NetworkOptions ==
\"
%s
\"
)
\n
"
,
Binding
,
debugstr_a
(
NetworkAddr
),
debugstr_a
(
Endpoint
),
debugstr_a
(
NetworkOptions
)
);
RPCRT4_strfree
(
Binding
->
NetworkAddr
);
Binding
->
NetworkAddr
=
RPCRT4_strdupA
(
NetworkAddr
);
...
...
@@ -183,31 +371,19 @@ RPC_STATUS RPCRT4_SetBindingObject(RpcBinding* Binding, UUID* ObjectUuid)
return
RPC_S_OK
;
}
RPC_STATUS
RPCRT4_
SpawnBinding
(
RpcBinding
**
Binding
,
RpcBinding
*
OldBinding
)
RPC_STATUS
RPCRT4_
MakeBinding
(
RpcBinding
**
Binding
,
RpcConnection
*
Connection
)
{
RpcBinding
*
NewBinding
;
if
(
Binding
)
TRACE
(
"(*RpcBinding == ^%p, OldBinding == ^%p)
\n
"
,
*
Binding
,
OldBinding
);
else
{
ERR
(
"!RpcBinding?"
);
/* we will crash below anyhow... */
*
((
char
*
)
0
)
=
0
;
}
TRACE
(
"(*RpcBinding == ^%p, Connection == ^%p)
\n
"
,
*
Binding
,
Connection
);
NewBinding
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
RpcBinding
));
NewBinding
->
refs
=
1
;
NewBinding
->
server
=
OldBinding
->
server
;
NewBinding
->
Protseq
=
RPCRT4_strdupA
(
OldBinding
->
Protseq
);
NewBinding
->
NetworkAddr
=
RPCRT4_strdupA
(
OldBinding
->
NetworkAddr
);
NewBinding
->
Endpoint
=
RPCRT4_strdupA
(
OldBinding
->
Endpoint
);
/* because of the way named pipes work, we'll transfer the connected pipe
* to the child, then reopen the server binding to continue listening */
NewBinding
->
conn
=
OldBinding
->
conn
;
NewBinding
->
ovl
=
OldBinding
->
ovl
;
OldBinding
->
conn
=
0
;
memset
(
&
OldBinding
->
ovl
,
0
,
sizeof
(
OldBinding
->
ovl
));
RPCRT4_AllocBinding
(
&
NewBinding
,
Connection
->
server
);
NewBinding
->
Protseq
=
RPCRT4_strdupA
(
Connection
->
Protseq
);
NewBinding
->
NetworkAddr
=
RPCRT4_strdupA
(
Connection
->
NetworkAddr
);
NewBinding
->
Endpoint
=
RPCRT4_strdupA
(
Connection
->
Endpoint
);
NewBinding
->
FromConn
=
Connection
;
TRACE
(
"binding: %p
\n
"
,
NewBinding
);
*
Binding
=
NewBinding
;
RPCRT4_OpenBinding
(
OldBinding
);
return
RPC_S_OK
;
}
...
...
@@ -225,7 +401,7 @@ RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
return
RPC_S_OK
;
TRACE
(
"binding: %p
\n
"
,
Binding
);
RPCRT4_CloseBinding
(
Binding
);
/* FIXME: release connections */
RPCRT4_strfree
(
Binding
->
Endpoint
);
RPCRT4_strfree
(
Binding
->
NetworkAddr
);
RPCRT4_strfree
(
Binding
->
Protseq
);
...
...
@@ -233,143 +409,29 @@ RPC_STATUS RPCRT4_DestroyBinding(RpcBinding* Binding)
return
RPC_S_OK
;
}
RPC_STATUS
RPCRT4_OpenBinding
(
RpcBinding
*
Binding
)
RPC_STATUS
RPCRT4_OpenBinding
(
RpcBinding
*
Binding
,
RpcConnection
**
Connection
)
{
RpcConnection
*
NewConnection
;
TRACE
(
"(Binding == ^%p)
\n
"
,
Binding
);
if
(
!
Binding
->
conn
)
{
if
(
Binding
->
server
)
{
/* server */
/* protseq=ncalrpc: supposed to use NT LPC ports,
* but we'll implement it with named pipes for now */
if
(
strcmp
(
Binding
->
Protseq
,
"ncalrpc"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
.
\\
pipe
\\
lrpc
\\
"
;
LPSTR
pname
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Binding
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Binding
->
Endpoint
);
TRACE
(
"listening on %s
\n
"
,
pname
);
Binding
->
conn
=
CreateNamedPipeA
(
pname
,
PIPE_ACCESS_DUPLEX
|
FILE_FLAG_OVERLAPPED
,
0
,
PIPE_UNLIMITED_INSTANCES
,
0
,
0
,
5000
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Binding
->
ovl
,
0
,
sizeof
(
Binding
->
ovl
));
Binding
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
if
(
!
ConnectNamedPipe
(
Binding
->
conn
,
&
Binding
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
==
ERROR_PIPE_CONNECTED
)
{
SetEvent
(
Binding
->
ovl
.
hEvent
);
return
RPC_S_OK
;
}
return
err
;
}
}
/* protseq=ncacn_np: named pipes */
else
if
(
strcmp
(
Binding
->
Protseq
,
"ncacn_np"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
."
;
LPSTR
pname
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Binding
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Binding
->
Endpoint
);
TRACE
(
"listening on %s
\n
"
,
pname
);
Binding
->
conn
=
CreateNamedPipeA
(
pname
,
PIPE_ACCESS_DUPLEX
|
FILE_FLAG_OVERLAPPED
,
0
,
PIPE_UNLIMITED_INSTANCES
,
0
,
0
,
5000
,
NULL
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Binding
->
ovl
,
0
,
sizeof
(
Binding
->
ovl
));
Binding
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
if
(
!
ConnectNamedPipe
(
Binding
->
conn
,
&
Binding
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
==
ERROR_PIPE_CONNECTED
)
{
SetEvent
(
Binding
->
ovl
.
hEvent
);
if
(
Binding
->
FromConn
)
{
*
Connection
=
Binding
->
FromConn
;
return
RPC_S_OK
;
}
return
err
;
}
}
else
{
ERR
(
"protseq %s not supported
\n
"
,
Binding
->
Protseq
);
return
RPC_S_PROTSEQ_NOT_SUPPORTED
;
}
}
else
{
/* client */
/* protseq=ncalrpc: supposed to use NT LPC ports,
* but we'll implement it with named pipes for now */
if
(
strcmp
(
Binding
->
Protseq
,
"ncalrpc"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
.
\\
pipe
\\
lrpc
\\
"
;
LPSTR
pname
;
HANDLE
conn
;
DWORD
err
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Binding
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Binding
->
Endpoint
);
TRACE
(
"connecting to %s
\n
"
,
pname
);
while
(
TRUE
)
{
if
(
WaitNamedPipeA
(
pname
,
NMPWAIT_WAIT_FOREVER
))
{
conn
=
CreateFileA
(
pname
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_OVERLAPPED
,
0
);
if
(
conn
!=
INVALID_HANDLE_VALUE
)
break
;
err
=
GetLastError
();
if
(
err
==
ERROR_PIPE_BUSY
)
continue
;
TRACE
(
"connection failed, error=%lx
\n
"
,
err
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
return
err
;
}
else
{
err
=
GetLastError
();
TRACE
(
"connection failed, error=%lx
\n
"
,
err
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
return
err
;
}
}
/* success */
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Binding
->
ovl
,
0
,
sizeof
(
Binding
->
ovl
));
Binding
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
Binding
->
conn
=
conn
;
}
/* protseq=ncacn_np: named pipes */
else
if
(
strcmp
(
Binding
->
Protseq
,
"ncacn_np"
)
==
0
)
{
static
LPSTR
prefix
=
"
\\\\
."
;
LPSTR
pname
;
HANDLE
conn
;
DWORD
err
;
pname
=
HeapAlloc
(
GetProcessHeap
(),
0
,
strlen
(
prefix
)
+
strlen
(
Binding
->
Endpoint
)
+
1
);
strcat
(
strcpy
(
pname
,
prefix
),
Binding
->
Endpoint
);
TRACE
(
"connecting to %s
\n
"
,
pname
);
conn
=
CreateFileA
(
pname
,
GENERIC_READ
|
GENERIC_WRITE
,
0
,
NULL
,
OPEN_EXISTING
,
FILE_FLAG_OVERLAPPED
,
0
);
if
(
conn
==
INVALID_HANDLE_VALUE
)
{
err
=
GetLastError
();
/* we don't need to handle ERROR_PIPE_BUSY here,
* the doc says that it is returned to the app */
TRACE
(
"connection failed, error=%lx
\n
"
,
err
);
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
return
err
;
}
/* success */
HeapFree
(
GetProcessHeap
(),
0
,
pname
);
memset
(
&
Binding
->
ovl
,
0
,
sizeof
(
Binding
->
ovl
));
Binding
->
ovl
.
hEvent
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
Binding
->
conn
=
conn
;
}
else
{
ERR
(
"protseq %s not supported
\n
"
,
Binding
->
Protseq
);
return
RPC_S_PROTSEQ_NOT_SUPPORTED
;
}
}
}
return
RPC_S_OK
;
/* FIXME: cache connections */
RPCRT4_CreateConnection
(
&
NewConnection
,
Binding
->
server
,
Binding
->
Protseq
,
Binding
->
NetworkAddr
,
Binding
->
Endpoint
,
NULL
);
NewConnection
->
Used
=
Binding
;
*
Connection
=
NewConnection
;
return
RPCRT4_OpenConnection
(
NewConnection
);
}
RPC_STATUS
RPCRT4_CloseBinding
(
RpcBinding
*
Binding
)
RPC_STATUS
RPCRT4_CloseBinding
(
RpcBinding
*
Binding
,
RpcConnection
*
Connection
)
{
TRACE
(
"(Binding == ^%p)
\n
"
,
Binding
);
if
(
Binding
->
conn
)
{
CancelIo
(
Binding
->
conn
);
CloseHandle
(
Binding
->
conn
);
Binding
->
conn
=
0
;
}
if
(
Binding
->
ovl
.
hEvent
)
{
CloseHandle
(
Binding
->
ovl
.
hEvent
);
Binding
->
ovl
.
hEvent
=
0
;
}
return
RPC_S_OK
;
if
(
!
Connection
)
return
RPC_S_OK
;
if
(
Binding
->
FromConn
==
Connection
)
return
RPC_S_OK
;
Connection
->
Used
=
NULL
;
return
RPCRT4_DestroyConnection
(
Connection
);
}
/* utility functions for string composing and parsing */
...
...
dlls/rpcrt4/rpc_binding.h
View file @
def211c4
...
...
@@ -23,20 +23,32 @@
#include "wine/rpcss_shared.h"
typedef
struct
_RpcConnection
{
struct
_RpcConnection
*
Next
;
struct
_RpcBinding
*
Used
;
BOOL
server
;
LPSTR
Protseq
;
LPSTR
NetworkAddr
;
LPSTR
Endpoint
;
HANDLE
conn
,
thread
;
OVERLAPPED
ovl
;
}
RpcConnection
;
/* don't know what MS's structure looks like */
typedef
struct
_RpcBinding
{
DWORD
refs
;
struct
_RpcBinding
*
Next
;
/* for rpc server */
struct
_RpcBinding
*
Next
;
BOOL
server
;
UUID
ObjectUuid
;
UUID
ActiveUuid
;
LPSTR
Protseq
;
LPSTR
NetworkAddr
;
LPSTR
Endpoint
;
RPC_BLOCKING_FN
BlockingFn
;
ULONG
ServerTid
;
HANDLE
conn
,
thread
;
OVERLAPPED
ovl
;
RpcConnection
*
FromConn
;
}
RpcBinding
;
LPSTR
RPCRT4_strndupA
(
LPSTR
src
,
INT
len
);
...
...
@@ -48,17 +60,23 @@ void RPCRT4_strfree(LPSTR src);
#define RPCRT4_strdupA(x) RPCRT4_strndupA((x),-1)
#define RPCRT4_strdupW(x) RPCRT4_strndupW((x),-1)
RPC_STATUS
RPCRT4_CreateConnection
(
RpcConnection
**
Connection
,
BOOL
server
,
LPSTR
Protseq
,
LPSTR
NetworkAddr
,
LPSTR
Endpoint
,
LPSTR
NetworkOptions
);
RPC_STATUS
RPCRT4_DestroyConnection
(
RpcConnection
*
Connection
);
RPC_STATUS
RPCRT4_OpenConnection
(
RpcConnection
*
Connection
);
RPC_STATUS
RPCRT4_CloseConnection
(
RpcConnection
*
Connection
);
RPC_STATUS
RPCRT4_SpawnConnection
(
RpcConnection
**
Connection
,
RpcConnection
*
OldConnection
);
RPC_STATUS
RPCRT4_CreateBindingA
(
RpcBinding
**
Binding
,
BOOL
server
,
LPSTR
Protseq
);
RPC_STATUS
RPCRT4_CreateBindingW
(
RpcBinding
**
Binding
,
BOOL
server
,
LPWSTR
Protseq
);
RPC_STATUS
RPCRT4_CompleteBindingA
(
RpcBinding
*
Binding
,
LPSTR
NetworkAddr
,
LPSTR
Endpoint
,
LPSTR
NetworkOptions
);
RPC_STATUS
RPCRT4_CompleteBindingW
(
RpcBinding
*
Binding
,
LPWSTR
NetworkAddr
,
LPWSTR
Endpoint
,
LPWSTR
NetworkOptions
);
RPC_STATUS
RPCRT4_ResolveBinding
(
RpcBinding
*
Binding
,
LPSTR
Endpoint
);
RPC_STATUS
RPCRT4_SetBindingObject
(
RpcBinding
*
Binding
,
UUID
*
ObjectUuid
);
RPC_STATUS
RPCRT4_
SpawnBinding
(
RpcBinding
**
Binding
,
RpcBinding
*
OldBinding
);
RPC_STATUS
RPCRT4_
MakeBinding
(
RpcBinding
**
Binding
,
RpcConnection
*
Connection
);
RPC_STATUS
RPCRT4_ExportBinding
(
RpcBinding
**
Binding
,
RpcBinding
*
OldBinding
);
RPC_STATUS
RPCRT4_DestroyBinding
(
RpcBinding
*
Binding
);
RPC_STATUS
RPCRT4_OpenBinding
(
RpcBinding
*
Binding
);
RPC_STATUS
RPCRT4_CloseBinding
(
RpcBinding
*
Binding
);
RPC_STATUS
RPCRT4_OpenBinding
(
RpcBinding
*
Binding
,
RpcConnection
**
Connection
);
RPC_STATUS
RPCRT4_CloseBinding
(
RpcBinding
*
Binding
,
RpcConnection
*
Connection
);
BOOL
RPCRT4_RPCSSOnDemandCall
(
PRPCSS_NP_MESSAGE
msg
,
char
*
vardata_payload
,
PRPCSS_NP_REPLY
reply
);
HANDLE
RPCRT4_GetMasterMutex
(
void
);
HANDLE
RPCRT4_RpcssNPConnect
(
void
);
...
...
dlls/rpcrt4/rpc_message.c
View file @
def211c4
...
...
@@ -48,9 +48,10 @@ RPC_STATUS WINAPI I_RpcGetBuffer(PRPC_MESSAGE pMsg)
{
void
*
buf
;
TRACE
(
"(%p)
\n
"
,
pMsg
);
TRACE
(
"(%p)
: BufferLength=%d
\n
"
,
pMsg
,
pMsg
->
BufferLength
);
/* FIXME: pfnAllocate? */
buf
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
pMsg
->
Buffer
,
pMsg
->
BufferLength
);
TRACE
(
"Buffer=%p
\n
"
,
buf
);
if
(
buf
)
pMsg
->
Buffer
=
buf
;
/* FIXME: which errors to return? */
return
buf
?
S_OK
:
E_OUTOFMEMORY
;
...
...
@@ -74,14 +75,23 @@ RPC_STATUS WINAPI I_RpcFreeBuffer(PRPC_MESSAGE pMsg)
RPC_STATUS
WINAPI
I_RpcSend
(
PRPC_MESSAGE
pMsg
)
{
RpcBinding
*
bind
=
(
RpcBinding
*
)
pMsg
->
Handle
;
RpcConnection
*
conn
;
RPC_CLIENT_INTERFACE
*
cif
=
NULL
;
RPC_SERVER_INTERFACE
*
sif
=
NULL
;
UUID
*
obj
;
UUID
*
act
;
RPC_STATUS
status
;
RpcPktHdr
hdr
;
TRACE
(
"(%p)
\n
"
,
pMsg
);
if
(
!
bind
)
return
RPC_S_INVALID_BINDING
;
status
=
RPCRT4_OpenBinding
(
bind
,
&
conn
);
if
(
status
!=
RPC_S_OK
)
return
status
;
obj
=
&
bind
->
ObjectUuid
;
act
=
&
bind
->
ActiveUuid
;
if
(
bind
->
server
)
{
sif
=
pMsg
->
RpcInterfaceInformation
;
if
(
!
sif
)
return
RPC_S_INTERFACE_NOT_FOUND
;
/* ? */
...
...
@@ -90,19 +100,17 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
if
(
!
cif
)
return
RPC_S_INTERFACE_NOT_FOUND
;
/* ? */
}
status
=
RPCRT4_OpenBinding
(
bind
);
if
(
status
!=
RPC_S_OK
)
return
status
;
/* initialize packet header */
memset
(
&
hdr
,
0
,
sizeof
(
hdr
));
hdr
.
rpc_ver
=
4
;
hdr
.
ptype
=
PKT_REQUEST
;
hdr
.
object
=
bind
->
ObjectUuid
;
/* FIXME: IIRC iff no object, the header structure excludes this elt */
hdr
.
ptype
=
bind
->
server
?
PKT_RESPONSE
:
PKT_REQUEST
;
hdr
.
object
=
*
obj
;
/* FIXME: IIRC iff no object, the header structure excludes this elt */
hdr
.
if_id
=
(
bind
->
server
)
?
sif
->
InterfaceId
.
SyntaxGUID
:
cif
->
InterfaceId
.
SyntaxGUID
;
hdr
.
if_vers
=
(
bind
->
server
)
?
MAKELONG
(
sif
->
InterfaceId
.
SyntaxVersion
.
MinorVersion
,
sif
->
InterfaceId
.
SyntaxVersion
.
MajorVersion
)
:
MAKELONG
(
cif
->
InterfaceId
.
SyntaxVersion
.
MinorVersion
,
cif
->
InterfaceId
.
SyntaxVersion
.
MajorVersion
);
hdr
.
act_id
=
*
act
;
hdr
.
opnum
=
pMsg
->
ProcNum
;
/* only the low-order 3 octets of the DataRepresentation go in the header */
hdr
.
drep
[
0
]
=
LOBYTE
(
LOWORD
(
pMsg
->
DataRepresentation
));
...
...
@@ -111,13 +119,26 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
hdr
.
len
=
pMsg
->
BufferLength
;
/* transmit packet */
if
(
!
WriteFile
(
bind
->
conn
,
&
hdr
,
sizeof
(
hdr
),
NULL
,
NULL
))
return
GetLastError
();
if
(
!
WriteFile
(
bind
->
conn
,
pMsg
->
Buffer
,
pMsg
->
BufferLength
,
NULL
,
NULL
))
return
GetLastError
();
if
(
!
WriteFile
(
conn
->
conn
,
&
hdr
,
sizeof
(
hdr
),
NULL
,
NULL
))
{
status
=
GetLastError
();
goto
fail
;
}
if
(
pMsg
->
BufferLength
&&
!
WriteFile
(
conn
->
conn
,
pMsg
->
Buffer
,
pMsg
->
BufferLength
,
NULL
,
NULL
))
{
status
=
GetLastError
();
goto
fail
;
}
/* success */
if
(
!
bind
->
server
)
{
/* save the connection, so the response can be read from it */
pMsg
->
ReservedForRuntime
=
conn
;
return
RPC_S_OK
;
}
RPCRT4_CloseBinding
(
bind
,
conn
);
status
=
RPC_S_OK
;
fail:
return
status
;
}
/***********************************************************************
...
...
@@ -126,6 +147,8 @@ RPC_STATUS WINAPI I_RpcSend(PRPC_MESSAGE pMsg)
RPC_STATUS
WINAPI
I_RpcReceive
(
PRPC_MESSAGE
pMsg
)
{
RpcBinding
*
bind
=
(
RpcBinding
*
)
pMsg
->
Handle
;
RpcConnection
*
conn
;
UUID
*
act
;
RPC_STATUS
status
;
RpcPktHdr
hdr
;
DWORD
dwRead
;
...
...
@@ -133,44 +156,78 @@ RPC_STATUS WINAPI I_RpcReceive(PRPC_MESSAGE pMsg)
TRACE
(
"(%p)
\n
"
,
pMsg
);
if
(
!
bind
)
return
RPC_S_INVALID_BINDING
;
status
=
RPCRT4_OpenBinding
(
bind
);
if
(
pMsg
->
ReservedForRuntime
)
{
conn
=
pMsg
->
ReservedForRuntime
;
pMsg
->
ReservedForRuntime
=
NULL
;
}
else
{
status
=
RPCRT4_OpenBinding
(
bind
,
&
conn
);
if
(
status
!=
RPC_S_OK
)
return
status
;
}
act
=
&
bind
->
ActiveUuid
;
for
(;;)
{
/* read packet header */
#ifdef OVERLAPPED_WORKS
if
(
!
ReadFile
(
bind
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
&
bind
->
ovl
))
{
if
(
!
ReadFile
(
conn
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
&
conn
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
!=
ERROR_IO_PENDING
)
{
return
err
;
status
=
err
;
goto
fail
;
}
if
(
!
GetOverlappedResult
(
conn
->
conn
,
&
conn
->
ovl
,
&
dwRead
,
TRUE
))
{
status
=
GetLastError
();
goto
fail
;
}
if
(
!
GetOverlappedResult
(
bind
->
conn
,
&
bind
->
ovl
,
&
dwRead
,
TRUE
))
return
GetLastError
();
}
#else
if
(
!
ReadFile
(
bind
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
NULL
))
return
GetLastError
();
if
(
!
ReadFile
(
conn
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
NULL
))
{
status
=
GetLastError
();
goto
fail
;
}
#endif
if
(
dwRead
!=
sizeof
(
hdr
))
return
RPC_S_PROTOCOL_ERROR
;
if
(
dwRead
!=
sizeof
(
hdr
))
{
status
=
RPC_S_PROTOCOL_ERROR
;
goto
fail
;
}
/* read packet body */
pMsg
->
BufferLength
=
hdr
.
len
;
status
=
I_RpcGetBuffer
(
pMsg
);
if
(
status
!=
RPC_S_OK
)
return
status
;
if
(
status
!=
RPC_S_OK
)
goto
fail
;
if
(
!
pMsg
->
BufferLength
)
dwRead
=
0
;
else
#ifdef OVERLAPPED_WORKS
if
(
!
ReadFile
(
bind
->
conn
,
pMsg
->
Buffer
,
hdr
.
len
,
&
dwRead
,
&
bind
->
ovl
))
{
if
(
!
ReadFile
(
conn
->
conn
,
pMsg
->
Buffer
,
hdr
.
len
,
&
dwRead
,
&
conn
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
!=
ERROR_IO_PENDING
)
{
return
err
;
status
=
err
;
goto
fail
;
}
if
(
!
GetOverlappedResult
(
conn
->
conn
,
&
conn
->
ovl
,
&
dwRead
,
TRUE
))
{
status
=
GetLastError
();
goto
fail
;
}
if
(
!
GetOverlappedResult
(
bind
->
conn
,
&
bind
->
ovl
,
&
dwRead
,
TRUE
))
return
GetLastError
();
}
#else
if
(
!
ReadFile
(
bind
->
conn
,
pMsg
->
Buffer
,
hdr
.
len
,
&
dwRead
,
NULL
))
return
GetLastError
();
if
(
!
ReadFile
(
conn
->
conn
,
pMsg
->
Buffer
,
hdr
.
len
,
&
dwRead
,
NULL
))
{
status
=
GetLastError
();
goto
fail
;
}
#endif
if
(
dwRead
!=
hdr
.
len
)
return
RPC_S_PROTOCOL_ERROR
;
if
(
dwRead
!=
hdr
.
len
)
{
status
=
RPC_S_PROTOCOL_ERROR
;
goto
fail
;
}
/* success */
return
RPC_S_OK
;
status
=
RPC_S_OK
;
/* FIXME: check packet type, destination, etc? */
break
;
}
fail:
RPCRT4_CloseBinding
(
bind
,
conn
);
return
status
;
}
/***********************************************************************
...
...
dlls/rpcrt4/rpc_server.c
View file @
def211c4
...
...
@@ -37,8 +37,18 @@
#include "rpc_server.h"
#include "rpc_defs.h"
#define MAX_THREADS 128
WINE_DEFAULT_DEBUG_CHANNEL
(
ole
);
typedef
struct
_RpcPacket
{
struct
_RpcPacket
*
next
;
struct
_RpcConnection
*
conn
;
RpcPktHdr
hdr
;
void
*
buf
;
}
RpcPacket
;
static
RpcServerProtseq
*
protseqs
;
static
RpcServerInterface
*
ifs
;
...
...
@@ -48,6 +58,13 @@ static BOOL std_listen;
static
LONG
listen_count
=
-
1
;
static
HANDLE
mgr_event
,
server_thread
;
static
CRITICAL_SECTION
spacket_cs
=
CRITICAL_SECTION_INIT
(
"RpcServerPacket"
);
static
RpcPacket
*
spacket_head
;
static
RpcPacket
*
spacket_tail
;
static
HANDLE
server_sem
;
static
DWORD
worker_count
,
worker_free
;
static
RpcServerInterface
*
RPCRT4_find_interface
(
UUID
*
object
,
UUID
*
if_id
)
{
UUID
*
MgrType
=
NULL
;
...
...
@@ -67,31 +84,168 @@ static RpcServerInterface* RPCRT4_find_interface(UUID* object, UUID* if_id)
return
cif
;
}
static
DWORD
CALLBACK
RPCRT4_io_thread
(
LPVOID
the_arg
)
static
void
RPCRT4_push_packet
(
RpcPacket
*
packet
)
{
RpcBinding
*
bind
=
(
RpcBinding
*
)
the_arg
;
RpcPktHdr
hdr
;
DWORD
dwRead
;
packet
->
next
=
NULL
;
EnterCriticalSection
(
&
spacket_cs
);
if
(
spacket_tail
)
spacket_tail
->
next
=
packet
;
else
{
spacket_head
=
packet
;
spacket_tail
=
packet
;
}
LeaveCriticalSection
(
&
spacket_cs
);
}
static
RpcPacket
*
RPCRT4_pop_packet
(
void
)
{
RpcPacket
*
packet
;
EnterCriticalSection
(
&
spacket_cs
);
packet
=
spacket_head
;
if
(
packet
)
{
spacket_head
=
packet
->
next
;
if
(
!
spacket_head
)
spacket_tail
=
NULL
;
}
LeaveCriticalSection
(
&
spacket_cs
);
if
(
packet
)
packet
->
next
=
NULL
;
return
packet
;
}
static
void
RPCRT4_process_packet
(
RpcConnection
*
conn
,
RpcPktHdr
*
hdr
,
void
*
buf
)
{
RpcBinding
*
pbind
;
RPC_MESSAGE
msg
;
RpcServerInterface
*
sif
;
RPC_DISPATCH_FUNCTION
func
;
memset
(
&
msg
,
0
,
sizeof
(
msg
));
msg
.
Handle
=
(
RPC_BINDING_HANDLE
)
bind
;
msg
.
BufferLength
=
hdr
->
len
;
msg
.
Buffer
=
buf
;
sif
=
RPCRT4_find_interface
(
&
hdr
->
object
,
&
hdr
->
if_id
);
if
(
sif
)
{
TRACE
(
"packet received for interface %s
\n
"
,
debugstr_guid
(
&
hdr
->
if_id
));
msg
.
RpcInterfaceInformation
=
sif
->
If
;
/* create temporary binding for dispatch */
RPCRT4_MakeBinding
(
&
pbind
,
conn
);
RPCRT4_SetBindingObject
(
pbind
,
&
hdr
->
object
);
msg
.
Handle
=
(
RPC_BINDING_HANDLE
)
pbind
;
/* process packet */
switch
(
hdr
->
ptype
)
{
case
PKT_REQUEST
:
/* find dispatch function */
msg
.
ProcNum
=
hdr
->
opnum
;
if
(
sif
->
Flags
&
RPC_IF_OLE
)
{
/* native ole32 always gives us a dispatch table with a single entry
* (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
func
=
*
sif
->
If
->
DispatchTable
->
DispatchTable
;
}
else
{
if
(
msg
.
ProcNum
>=
sif
->
If
->
DispatchTable
->
DispatchTableCount
)
{
ERR
(
"invalid procnum
\n
"
);
func
=
NULL
;
}
func
=
sif
->
If
->
DispatchTable
->
DispatchTable
[
msg
.
ProcNum
];
}
/* put in the drep. FIXME: is this more universally applicable?
perhaps we should move this outward... */
msg
.
DataRepresentation
=
MAKELONG
(
MAKEWORD
(
hdr
->
drep
[
0
],
hdr
->
drep
[
1
]),
MAKEWORD
(
hdr
->
drep
[
2
],
0
));
/* dispatch */
if
(
func
)
func
(
&
msg
);
/* send response packet */
I_RpcSend
(
&
msg
);
break
;
default:
ERR
(
"unknown packet type
\n
"
);
break
;
}
RPCRT4_DestroyBinding
(
pbind
);
msg
.
Handle
=
0
;
msg
.
RpcInterfaceInformation
=
NULL
;
}
else
{
ERR
(
"got RPC packet to unregistered interface %s
\n
"
,
debugstr_guid
(
&
hdr
->
if_id
));
}
/* clean up */
HeapFree
(
GetProcessHeap
(),
0
,
msg
.
Buffer
);
msg
.
Buffer
=
NULL
;
}
static
DWORD
CALLBACK
RPCRT4_worker_thread
(
LPVOID
the_arg
)
{
DWORD
obj
;
RpcPacket
*
pkt
;
for
(;;)
{
/* idle timeout after 5s */
obj
=
WaitForSingleObject
(
server_sem
,
5000
);
if
(
obj
==
WAIT_TIMEOUT
)
{
/* if another idle thread exist, self-destruct */
if
(
worker_free
>
1
)
break
;
continue
;
}
pkt
=
RPCRT4_pop_packet
();
if
(
!
pkt
)
continue
;
InterlockedDecrement
(
&
worker_free
);
for
(;;)
{
RPCRT4_process_packet
(
pkt
->
conn
,
&
pkt
->
hdr
,
pkt
->
buf
);
HeapFree
(
GetProcessHeap
(),
0
,
pkt
);
/* try to grab another packet here without waiting
* on the semaphore, in case it hits max */
pkt
=
RPCRT4_pop_packet
();
if
(
!
pkt
)
break
;
/* decrement semaphore */
WaitForSingleObject
(
server_sem
,
0
);
}
InterlockedIncrement
(
&
worker_free
);
}
InterlockedDecrement
(
&
worker_free
);
InterlockedDecrement
(
&
worker_count
);
return
0
;
}
static
void
RPCRT4_create_worker_if_needed
(
void
)
{
if
(
!
worker_free
&&
worker_count
<
MAX_THREADS
)
{
HANDLE
thread
;
InterlockedIncrement
(
&
worker_count
);
InterlockedIncrement
(
&
worker_free
);
thread
=
CreateThread
(
NULL
,
0
,
RPCRT4_worker_thread
,
NULL
,
0
,
NULL
);
if
(
thread
)
CloseHandle
(
thread
);
else
{
InterlockedDecrement
(
&
worker_free
);
InterlockedDecrement
(
&
worker_count
);
}
}
}
static
DWORD
CALLBACK
RPCRT4_io_thread
(
LPVOID
the_arg
)
{
RpcConnection
*
conn
=
(
RpcConnection
*
)
the_arg
;
RpcPktHdr
hdr
;
DWORD
dwRead
;
void
*
buf
=
NULL
;
RpcPacket
*
packet
;
TRACE
(
"(%p)
\n
"
,
conn
);
for
(;;)
{
/* read packet header */
#ifdef OVERLAPPED_WORKS
if
(
!
ReadFile
(
bind
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
&
bind
->
ovl
))
{
if
(
!
ReadFile
(
conn
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
&
conn
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
!=
ERROR_IO_PENDING
)
{
TRACE
(
"connection lost, error=%08lx
\n
"
,
err
);
break
;
}
if
(
!
GetOverlappedResult
(
bind
->
conn
,
&
bind
->
ovl
,
&
dwRead
,
TRUE
))
break
;
if
(
!
GetOverlappedResult
(
conn
->
conn
,
&
conn
->
ovl
,
&
dwRead
,
TRUE
))
break
;
}
#else
if
(
!
ReadFile
(
bind
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
NULL
))
{
if
(
!
ReadFile
(
conn
->
conn
,
&
hdr
,
sizeof
(
hdr
),
&
dwRead
,
NULL
))
{
TRACE
(
"connection lost, error=%08lx
\n
"
,
GetLastError
());
break
;
}
...
...
@@ -102,19 +256,20 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
}
/* read packet body */
msg
.
BufferLength
=
hdr
.
len
;
msg
.
Buffer
=
HeapAlloc
(
GetProcessHeap
(),
0
,
msg
.
BufferLength
);
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
hdr
.
len
);
TRACE
(
"receiving payload=%d
\n
"
,
hdr
.
len
);
if
(
!
hdr
.
len
)
dwRead
=
0
;
else
#ifdef OVERLAPPED_WORKS
if
(
!
ReadFile
(
bind
->
conn
,
msg
.
Buffer
,
msg
.
BufferLength
,
&
dwRead
,
&
bind
->
ovl
))
{
if
(
!
ReadFile
(
conn
->
conn
,
buf
,
hdr
.
len
,
&
dwRead
,
&
conn
->
ovl
))
{
DWORD
err
=
GetLastError
();
if
(
err
!=
ERROR_IO_PENDING
)
{
TRACE
(
"connection lost, error=%08lx
\n
"
,
err
);
break
;
}
if
(
!
GetOverlappedResult
(
bind
->
conn
,
&
bind
->
ovl
,
&
dwRead
,
TRUE
))
break
;
if
(
!
GetOverlappedResult
(
conn
->
conn
,
&
conn
->
ovl
,
&
dwRead
,
TRUE
))
break
;
}
#else
if
(
!
ReadFile
(
bind
->
conn
,
msg
.
Buffer
,
msg
.
BufferLength
,
&
dwRead
,
NULL
))
{
if
(
!
ReadFile
(
conn
->
conn
,
buf
,
hdr
.
len
,
&
dwRead
,
NULL
))
{
TRACE
(
"connection lost, error=%08lx
\n
"
,
GetLastError
());
break
;
}
...
...
@@ -124,72 +279,31 @@ static DWORD CALLBACK RPCRT4_io_thread(LPVOID the_arg)
break
;
}
sif
=
RPCRT4_find_interface
(
&
hdr
.
object
,
&
hdr
.
if_id
);
if
(
sif
)
{
msg
.
RpcInterfaceInformation
=
sif
->
If
;
/* associate object with binding (this is a bit of a hack...
* a new binding should probably be created for each object) */
RPCRT4_SetBindingObject
(
bind
,
&
hdr
.
object
);
/* process packet*/
switch
(
hdr
.
ptype
)
{
case
PKT_REQUEST
:
/* find dispatch function */
msg
.
ProcNum
=
hdr
.
opnum
;
if
(
sif
->
Flags
&
RPC_IF_OLE
)
{
/* native ole32 always gives us a dispatch table with a single entry
* (I assume that's a wrapper for IRpcStubBuffer::Invoke) */
func
=
*
sif
->
If
->
DispatchTable
->
DispatchTable
;
}
else
{
if
(
msg
.
ProcNum
>=
sif
->
If
->
DispatchTable
->
DispatchTableCount
)
{
ERR
(
"invalid procnum
\n
"
);
func
=
NULL
;
}
func
=
sif
->
If
->
DispatchTable
->
DispatchTable
[
msg
.
ProcNum
];
}
/* put in the drep. FIXME: is this more universally applicable?
perhaps we should move this outward... */
msg
.
DataRepresentation
=
MAKELONG
(
MAKEWORD
(
hdr
.
drep
[
0
],
hdr
.
drep
[
1
]),
MAKEWORD
(
hdr
.
drep
[
2
],
0
));
/* dispatch */
if
(
func
)
func
(
&
msg
);
/* prepare response packet */
hdr
.
ptype
=
PKT_RESPONSE
;
break
;
default:
ERR
(
"unknown packet type
\n
"
);
goto
no_reply
;
}
/* write reply packet */
hdr
.
len
=
msg
.
BufferLength
;
WriteFile
(
bind
->
conn
,
&
hdr
,
sizeof
(
hdr
),
NULL
,
NULL
);
WriteFile
(
bind
->
conn
,
msg
.
Buffer
,
msg
.
BufferLength
,
NULL
,
NULL
);
no_reply:
/* un-associate object */
RPCRT4_SetBindingObject
(
bind
,
NULL
);
msg
.
RpcInterfaceInformation
=
NULL
;
}
else
{
ERR
(
"got RPC packet to unregistered interface %s
\n
"
,
debugstr_guid
(
&
hdr
.
if_id
));
}
/* clean up */
HeapFree
(
GetProcessHeap
(),
0
,
msg
.
Buffer
);
msg
.
Buffer
=
NULL
;
#if 0
RPCRT4_process_packet(conn, &hdr, buf);
#else
packet
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
RpcPacket
));
packet
->
conn
=
conn
;
packet
->
hdr
=
hdr
;
packet
->
buf
=
buf
;
RPCRT4_create_worker_if_needed
();
RPCRT4_push_packet
(
packet
);
ReleaseSemaphore
(
server_sem
,
1
,
NULL
);
#endif
buf
=
NULL
;
}
if
(
msg
.
Buffer
)
HeapFree
(
GetProcessHeap
(),
0
,
msg
.
Buffer
);
RPCRT4_Destroy
Binding
(
bind
);
if
(
buf
)
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
RPCRT4_Destroy
Connection
(
conn
);
return
0
;
}
static
void
RPCRT4_new_client
(
Rpc
Binding
*
bind
)
static
void
RPCRT4_new_client
(
Rpc
Connection
*
conn
)
{
bind
->
thread
=
CreateThread
(
NULL
,
0
,
RPCRT4_io_thread
,
bind
,
0
,
NULL
);
conn
->
thread
=
CreateThread
(
NULL
,
0
,
RPCRT4_io_thread
,
conn
,
0
,
NULL
);
if
(
!
conn
->
thread
)
{
DWORD
err
=
GetLastError
();
ERR
(
"failed to create thread, error=%08lx
\n
"
,
err
);
}
}
static
DWORD
CALLBACK
RPCRT4_server_thread
(
LPVOID
the_arg
)
...
...
@@ -198,33 +312,33 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
HANDLE
*
objs
=
NULL
;
DWORD
count
,
res
;
RpcServerProtseq
*
cps
;
Rpc
Binding
*
bind
;
Rpc
Binding
*
cbind
;
Rpc
Connection
*
conn
;
Rpc
Connection
*
cconn
;
for
(;;)
{
EnterCriticalSection
(
&
server_cs
);
/* open and count
binding
s */
/* open and count
connection
s */
count
=
1
;
cps
=
protseqs
;
while
(
cps
)
{
bind
=
cps
->
bind
;
while
(
bind
)
{
RPCRT4_OpenBinding
(
bind
);
if
(
bind
->
ovl
.
hEvent
)
count
++
;
bind
=
bind
->
Next
;
conn
=
cps
->
conn
;
while
(
conn
)
{
RPCRT4_OpenConnection
(
conn
);
if
(
conn
->
ovl
.
hEvent
)
count
++
;
conn
=
conn
->
Next
;
}
cps
=
cps
->
Next
;
}
/* make array of
bind
ings */
/* make array of
conn
ings */
objs
=
HeapReAlloc
(
GetProcessHeap
(),
0
,
objs
,
count
*
sizeof
(
HANDLE
));
objs
[
0
]
=
m_event
;
count
=
1
;
cps
=
protseqs
;
while
(
cps
)
{
bind
=
cps
->
bind
;
while
(
bind
)
{
if
(
bind
->
ovl
.
hEvent
)
objs
[
count
++
]
=
bind
->
ovl
.
hEvent
;
bind
=
bind
->
Next
;
conn
=
cps
->
conn
;
while
(
conn
)
{
if
(
conn
->
ovl
.
hEvent
)
objs
[
count
++
]
=
conn
->
ovl
.
hEvent
;
conn
=
conn
->
Next
;
}
cps
=
cps
->
Next
;
}
...
...
@@ -241,37 +355,37 @@ static DWORD CALLBACK RPCRT4_server_thread(LPVOID the_arg)
}
else
{
b_handle
=
objs
[
res
-
WAIT_OBJECT_0
];
/* find which
binding
got a RPC */
/* find which
connection
got a RPC */
EnterCriticalSection
(
&
server_cs
);
bind
=
NULL
;
conn
=
NULL
;
cps
=
protseqs
;
while
(
cps
)
{
bind
=
cps
->
bind
;
while
(
bind
)
{
if
(
bind
->
ovl
.
hEvent
==
b_handle
)
break
;
bind
=
bind
->
Next
;
conn
=
cps
->
conn
;
while
(
conn
)
{
if
(
conn
->
ovl
.
hEvent
==
b_handle
)
break
;
conn
=
conn
->
Next
;
}
if
(
bind
)
break
;
if
(
conn
)
break
;
cps
=
cps
->
Next
;
}
c
bind
=
NULL
;
if
(
bind
)
RPCRT4_SpawnBinding
(
&
cbind
,
bind
);
c
conn
=
NULL
;
if
(
conn
)
RPCRT4_SpawnConnection
(
&
cconn
,
conn
);
LeaveCriticalSection
(
&
server_cs
);
if
(
!
bind
)
{
ERR
(
"failed to locate
binding
for handle %p
\n
"
,
b_handle
);
if
(
!
conn
)
{
ERR
(
"failed to locate
connection
for handle %p
\n
"
,
b_handle
);
}
if
(
c
bind
)
RPCRT4_new_client
(
cbind
);
if
(
c
conn
)
RPCRT4_new_client
(
cconn
);
}
}
HeapFree
(
GetProcessHeap
(),
0
,
objs
);
EnterCriticalSection
(
&
server_cs
);
/* close
binding
s */
/* close
connection
s */
cps
=
protseqs
;
while
(
cps
)
{
bind
=
cps
->
bind
;
while
(
bind
)
{
RPCRT4_Close
Binding
(
bind
);
bind
=
bind
->
Next
;
conn
=
cps
->
conn
;
while
(
conn
)
{
RPCRT4_Close
Connection
(
conn
);
conn
=
conn
->
Next
;
}
cps
=
cps
->
Next
;
}
...
...
@@ -286,6 +400,7 @@ static void RPCRT4_start_listen(void)
EnterCriticalSection
(
&
listen_cs
);
if
(
!
++
listen_count
)
{
if
(
!
mgr_event
)
mgr_event
=
CreateEventA
(
NULL
,
TRUE
,
FALSE
,
NULL
);
if
(
!
server_sem
)
server_sem
=
CreateSemaphoreA
(
NULL
,
0
,
MAX_THREADS
,
NULL
);
std_listen
=
TRUE
;
server_thread
=
CreateThread
(
NULL
,
0
,
RPCRT4_server_thread
,
NULL
,
0
,
NULL
);
LeaveCriticalSection
(
&
listen_cs
);
...
...
@@ -311,8 +426,7 @@ static void RPCRT4_stop_listen(void)
static
RPC_STATUS
RPCRT4_use_protseq
(
RpcServerProtseq
*
ps
)
{
RPCRT4_CreateBindingA
(
&
ps
->
bind
,
TRUE
,
ps
->
Protseq
);
RPCRT4_CompleteBindingA
(
ps
->
bind
,
NULL
,
ps
->
Endpoint
,
NULL
);
RPCRT4_CreateConnection
(
&
ps
->
conn
,
TRUE
,
ps
->
Protseq
,
NULL
,
ps
->
Endpoint
,
NULL
);
EnterCriticalSection
(
&
server_cs
);
ps
->
Next
=
protseqs
;
...
...
@@ -332,7 +446,7 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
RPC_STATUS
status
;
DWORD
count
;
RpcServerProtseq
*
ps
;
Rpc
Binding
*
bind
;
Rpc
Connection
*
conn
;
if
(
BindingVector
)
TRACE
(
"(*BindingVector == ^%p)
\n
"
,
*
BindingVector
);
...
...
@@ -340,14 +454,14 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
ERR
(
"(BindingVector == ^null!!?)
\n
"
);
EnterCriticalSection
(
&
server_cs
);
/* count
binding
s */
/* count
connection
s */
count
=
0
;
ps
=
protseqs
;
while
(
ps
)
{
bind
=
ps
->
bind
;
while
(
bind
)
{
conn
=
ps
->
conn
;
while
(
conn
)
{
count
++
;
bind
=
bind
->
Next
;
conn
=
conn
->
Next
;
}
ps
=
ps
->
Next
;
}
...
...
@@ -360,12 +474,12 @@ RPC_STATUS WINAPI RpcServerInqBindings( RPC_BINDING_VECTOR** BindingVector )
count
=
0
;
ps
=
protseqs
;
while
(
ps
)
{
bind
=
ps
->
bind
;
while
(
bind
)
{
RPCRT4_
Export
Binding
((
RpcBinding
**
)
&
(
*
BindingVector
)
->
BindingH
[
count
],
bind
);
conn
=
ps
->
conn
;
while
(
conn
)
{
RPCRT4_
Make
Binding
((
RpcBinding
**
)
&
(
*
BindingVector
)
->
BindingH
[
count
],
conn
);
count
++
;
bind
=
bind
->
Next
;
conn
=
conn
->
Next
;
}
ps
=
ps
->
Next
;
}
...
...
dlls/rpcrt4/rpc_server.h
View file @
def211c4
...
...
@@ -29,7 +29,7 @@ typedef struct _RpcServerProtseq
LPSTR
Protseq
;
LPSTR
Endpoint
;
UINT
MaxCalls
;
Rpc
Binding
*
bind
;
Rpc
Connection
*
conn
;
}
RpcServerProtseq
;
typedef
struct
_RpcServerInterface
...
...
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