2 * Copyright 2001, Ove Kåven, TransGaming Technologies Inc.
3 * Copyright 2002 Greg Turner
5 * This library is free software; you can redistribute it and/or
6 * modify it under the terms of the GNU Lesser General Public
7 * License as published by the Free Software Foundation; either
8 * version 2.1 of the License, or (at your option) any later version.
10 * This library is distributed in the hope that it will be useful,
11 * but WITHOUT ANY WARRANTY; without even the implied warranty of
12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 * Lesser General Public License for more details.
15 * You should have received a copy of the GNU Lesser General Public
16 * License along with this library; if not, write to the Free Software
17 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
20 * Initialize and start serving requests. Bail if rpcss already is
25 * Wine needs a server whose role is somewhat like that
26 * of rpcss.exe in windows. This is not a clone of
27 * windows rpcss at all. It has been given the same name, however,
28 * to provide for the possibility that at some point in the future,
29 * it may become interface compatible with the "real" rpcss.exe on
32 * ---- KNOWN BUGS / TODO:
34 * o Service hooks are unimplemented (if you bother to implement
35 * these, also implement net.exe, at least for "net start" and
36 * "net stop" (should be pretty easy I guess, assuming the rest
37 * of the services API infrastructure works.
39 * o Is supposed to use RPC, not random kludges, to map endpoints.
41 * o Probably name services should be implemented here as well.
43 * o Wine's named pipes (in general) may not interoperate with those of
46 * o There is a looming problem regarding listening on privileged
47 * ports. We will need to be able to coexist with SAMBA, and be able
48 * to function without running winelib code as root. This may
49 * take some doing, including significant reconceptualization of the
50 * role of rpcss.exe in wine.
52 * o Who knows? Whatever rpcss does, we ought to at
53 * least think about doing... but what /does/ it do?
61 #define NONAMELESSUNION
62 #define NONAMELESSSTRUCT
66 #include "wine/debug.h"
68 WINE_DEFAULT_DEBUG_CHANNEL(ole
);
70 static HANDLE master_mutex
;
71 static long max_lazy_timeout
= RPCSS_DEFAULT_MAX_LAZY_TIMEOUT
;
73 HANDLE
RPCSS_GetMasterMutex(void)
78 void RPCSS_SetMaxLazyTimeout(long mlt
)
80 /* FIXME: this max ensures that no caller will decrease our wait time,
81 but could have other bad results. fix: Store "next_max_lazy_timeout"
82 and install it as necessary next time we "do work"? */
83 max_lazy_timeout
= max(RPCSS_GetLazyTimeRemaining(), mlt
);
86 long RPCSS_GetMaxLazyTimeout(void)
88 return max_lazy_timeout
;
91 /* when do we just give up and bail? (UTC) */
92 static SYSTEMTIME lazy_timeout_time
;
94 #if defined(NONAMELESSSTRUCT)
95 #define FILETIME_TO_ULARGEINT(filetime, ularge) \
96 ( ularge.s.LowPart = filetime.dwLowDateTime, \
97 ularge.s.HighPart = filetime.dwHighDateTime )
98 #define ULARGEINT_TO_FILETIME(ularge, filetime) \
99 ( filetime.dwLowDateTime = ularge.s.LowPart, \
100 filetime.dwHighDateTime = ularge.s.HighPart )
102 #define FILETIME_TO_ULARGEINT(filetime, ularge) \
103 ( ularge.LowPart = filetime.dwLowDateTime, \
104 ularge.HighPart = filetime.dwHighDateTime )
105 #define ULARGEINT_TO_FILETIME(ularge, filetime) \
106 ( filetime.dwLowDateTime = ularge.LowPart, \
107 filetime.dwHighDateTime = ularge.HighPart )
108 #endif /* NONAMELESSSTRUCT */
110 #define TEN_MIL 10000000LL
112 /* returns time remaining in seconds */
113 long RPCSS_GetLazyTimeRemaining(void)
115 SYSTEMTIME st_just_now
;
116 FILETIME ft_jn
, ft_ltt
;
117 ULARGE_INTEGER ul_jn
, ul_ltt
;
119 GetSystemTime(&st_just_now
);
120 SystemTimeToFileTime(&st_just_now
, &ft_jn
);
121 FILETIME_TO_ULARGEINT(ft_jn
, ul_jn
);
123 SystemTimeToFileTime(&lazy_timeout_time
, &ft_ltt
);
124 FILETIME_TO_ULARGEINT(ft_ltt
, ul_ltt
);
126 if (ul_jn
.QuadPart
> ul_ltt
.QuadPart
)
129 return (ul_ltt
.QuadPart
- ul_jn
.QuadPart
) / TEN_MIL
;
132 void RPCSS_SetLazyTimeRemaining(long seconds
)
134 SYSTEMTIME st_just_now
;
135 FILETIME ft_jn
, ft_ltt
;
136 ULARGE_INTEGER ul_jn
, ul_ltt
;
138 WINE_TRACE("(seconds == %ld)\n", seconds
);
140 assert(seconds
>= 0); /* negatives are not allowed */
142 GetSystemTime(&st_just_now
);
143 SystemTimeToFileTime(&st_just_now
, &ft_jn
);
144 FILETIME_TO_ULARGEINT(ft_jn
, ul_jn
);
146 /* we want to find the time ltt, s.t. ltt = just_now + seconds */
147 ul_ltt
.QuadPart
= ul_jn
.QuadPart
+ seconds
* TEN_MIL
;
149 /* great. just remember it */
150 ULARGEINT_TO_FILETIME(ul_ltt
, ft_ltt
);
151 if (! FileTimeToSystemTime(&ft_ltt
, &lazy_timeout_time
))
155 #undef FILETIME_TO_ULARGEINT
156 #undef ULARGEINT_TO_FILETIME
159 BOOL
RPCSS_work(void)
161 return RPCSS_NPDoWork();
164 BOOL
RPCSS_Empty(void)
168 rslt
= RPCSS_EpmapEmpty();
173 BOOL
RPCSS_ReadyToDie(void)
175 long ltr
= RPCSS_GetLazyTimeRemaining();
176 LONG stc
= RPCSS_SrvThreadCount();
177 BOOL empty
= RPCSS_Empty();
178 return ( empty
&& (ltr
<= 0) && (stc
== 0) );
181 BOOL
RPCSS_Initialize(void)
185 master_mutex
= CreateMutexA( NULL
, FALSE
, RPCSS_MASTER_MUTEX_NAME
);
187 WINE_ERR("Failed to create master mutex\n");
191 if (!RPCSS_BecomePipeServer()) {
192 WINE_WARN("Server already running: exiting.\n");
194 CloseHandle(master_mutex
);
203 /* returns false if we discover at the last moment that we
204 aren't ready to terminate */
205 BOOL
RPCSS_Shutdown(void)
207 if (!RPCSS_UnBecomePipeServer())
210 if (!CloseHandle(master_mutex
))
211 WINE_WARN("Failed to release master mutex\n");
218 void RPCSS_MainLoop(void)
220 BOOL did_something_new
;
225 did_something_new
= FALSE
;
227 while ( (! did_something_new
) && (! RPCSS_ReadyToDie()) )
228 did_something_new
= (RPCSS_work() || did_something_new
);
230 if ((! did_something_new
) && RPCSS_ReadyToDie())
231 break; /* that's it for us */
233 if (did_something_new
)
234 RPCSS_SetLazyTimeRemaining(max_lazy_timeout
);
238 BOOL
RPCSS_ProcessArgs( int argc
, char **argv
)
243 for (i
= 1; i
< argc
; i
++) {
245 while (*c
== ' ') c
++;
246 if ((*c
!= '-') && (*c
!= '/'))
252 while (*c
== ' ') c
++;
258 while (*c
== ' ') c
++;
263 max_lazy_timeout
= strtol(c
, &c1
, 0);
267 if (max_lazy_timeout
<= 0)
269 if (max_lazy_timeout
== LONG_MAX
)
271 WINE_TRACE("read timeout argument: %ld\n", max_lazy_timeout
);
277 while (*c
== ' ') c
++;
278 if (*c
!= '\0') return FALSE
;
284 void RPCSS_Usage(void)
286 printf("\nWine RPCSS\n");
287 printf("\nsyntax: rpcss [-t timeout]\n\n");
288 printf(" -t: rpcss (or the running rpcss process) will\n");
289 printf(" execute with at least the specified timeout.\n");
293 int main( int argc
, char **argv
)
296 * We are invoked as a standard executable; we act in a
297 * "lazy" manner. We open up our pipe, and hang around until we have
298 * nothing left to do, and then silently terminate. When we're needed
299 * again, rpcrt4.dll.so will invoke us automatically.
302 if (!RPCSS_ProcessArgs(argc
, argv
)) {
307 /* we want to wait for something to happen, and then
308 timeout when no activity occurs. */
309 RPCSS_SetLazyTimeRemaining(max_lazy_timeout
);
311 if (RPCSS_Initialize()) {
314 while (!RPCSS_Shutdown());