Skip to content
Projects
Groups
Snippets
Help
This project
Loading...
Sign in / Register
Toggle navigation
W
wine-cw
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-cw
Commits
a1fbd550
Commit
a1fbd550
authored
Mar 15, 2008
by
Mikołaj Zalewski
Committed by
Alexandre Julliard
Mar 28, 2008
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
services.exe: Load list of services from registry at startup.
parent
7bd0efa1
Hide whitespace changes
Inline
Side-by-side
Showing
4 changed files
with
374 additions
and
1 deletion
+374
-1
Makefile.in
programs/services/Makefile.in
+3
-1
services.c
programs/services/services.c
+176
-0
services.h
programs/services/services.h
+48
-0
utils.c
programs/services/utils.c
+147
-0
No files found.
programs/services/Makefile.in
View file @
a1fbd550
...
...
@@ -5,9 +5,11 @@ VPATH = @srcdir@
MODULE
=
services.exe
APPMODE
=
-mconsole
IMPORTS
=
kernel32
IMPORTS
=
advapi32 kernel32
C_SRCS
=
\
services.c
services.c
\
utils.c
@MAKE_PROG_RULES@
...
...
programs/services/services.c
View file @
a1fbd550
...
...
@@ -21,8 +21,184 @@
#define WIN32_LEAN_AND_MEAN
#include <stdarg.h>
#include <windows.h>
#include <winsvc.h>
#include "wine/list.h"
#include "wine/unicode.h"
#include "wine/debug.h"
#include "services.h"
#define MAX_SERVICE_NAME 260
WINE_DEFAULT_DEBUG_CHANNEL
(
service
);
static
struct
list
g_services
;
/* Registry constants */
static
const
WCHAR
SZ_SERVICES_KEY
[]
=
{
'S'
,
'y'
,
's'
,
't'
,
'e'
,
'm'
,
'\\'
,
'C'
,
'u'
,
'r'
,
'r'
,
'e'
,
'n'
,
't'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
'S'
,
'e'
,
't'
,
'\\'
,
'S'
,
'e'
,
'r'
,
'v'
,
'i'
,
'c'
,
'e'
,
's'
,
0
};
/* Service key values names */
static
const
WCHAR
SZ_DISPLAY_NAME
[]
=
{
'D'
,
'i'
,
's'
,
'p'
,
'l'
,
'a'
,
'y'
,
'N'
,
'a'
,
'm'
,
'e'
,
0
};
static
const
WCHAR
SZ_TYPE
[]
=
{
'T'
,
'y'
,
'p'
,
'e'
,
0
};
static
const
WCHAR
SZ_START
[]
=
{
'S'
,
't'
,
'a'
,
'r'
,
't'
,
0
};
static
const
WCHAR
SZ_ERROR
[]
=
{
'E'
,
'r'
,
'r'
,
'o'
,
'r'
,
'C'
,
'o'
,
'n'
,
't'
,
'r'
,
'o'
,
'l'
,
0
};
static
const
WCHAR
SZ_IMAGE_PATH
[]
=
{
'I'
,
'm'
,
'a'
,
'g'
,
'e'
,
'P'
,
'a'
,
't'
,
'h'
,
0
};
static
const
WCHAR
SZ_GROUP
[]
=
{
'G'
,
'r'
,
'o'
,
'u'
,
'p'
,
0
};
static
const
WCHAR
SZ_DEPEND_ON_SERVICE
[]
=
{
'D'
,
'e'
,
'p'
,
'e'
,
'n'
,
'd'
,
'O'
,
'n'
,
'S'
,
'e'
,
'r'
,
'v'
,
'i'
,
'c'
,
'e'
,
0
};
static
const
WCHAR
SZ_DEPEND_ON_GROUP
[]
=
{
'D'
,
'e'
,
'p'
,
'e'
,
'n'
,
'd'
,
'O'
,
'n'
,
'G'
,
'r'
,
'o'
,
'u'
,
'p'
,
0
};
static
const
WCHAR
SZ_OBJECT_NAME
[]
=
{
'O'
,
'b'
,
'j'
,
'e'
,
'c'
,
't'
,
'N'
,
'a'
,
'm'
,
'e'
,
0
};
static
const
WCHAR
SZ_TAG
[]
=
{
'T'
,
'a'
,
'g'
,
0
};
static
const
WCHAR
SZ_DESCRIPTION
[]
=
{
'D'
,
'e'
,
's'
,
'c'
,
'r'
,
'i'
,
'p'
,
't'
,
'i'
,
'o'
,
'n'
,
0
};
static
void
free_service_entry
(
struct
service_entry
*
entry
)
{
HeapFree
(
GetProcessHeap
(),
0
,
entry
->
name
);
HeapFree
(
GetProcessHeap
(),
0
,
entry
->
config
.
lpBinaryPathName
);
HeapFree
(
GetProcessHeap
(),
0
,
entry
->
config
.
lpDependencies
);
HeapFree
(
GetProcessHeap
(),
0
,
entry
->
config
.
lpLoadOrderGroup
);
HeapFree
(
GetProcessHeap
(),
0
,
entry
->
config
.
lpServiceStartName
);
HeapFree
(
GetProcessHeap
(),
0
,
entry
->
config
.
lpDisplayName
);
HeapFree
(
GetProcessHeap
(),
0
,
entry
->
description
);
HeapFree
(
GetProcessHeap
(),
0
,
entry
);
}
static
DWORD
load_service_config
(
HKEY
hKey
,
struct
service_entry
*
entry
)
{
DWORD
err
;
WCHAR
*
wptr
;
if
((
err
=
load_reg_string
(
hKey
,
SZ_IMAGE_PATH
,
TRUE
,
&
entry
->
config
.
lpBinaryPathName
))
!=
0
)
return
err
;
if
((
err
=
load_reg_string
(
hKey
,
SZ_GROUP
,
0
,
&
entry
->
config
.
lpLoadOrderGroup
))
!=
0
)
return
err
;
if
((
err
=
load_reg_string
(
hKey
,
SZ_OBJECT_NAME
,
TRUE
,
&
entry
->
config
.
lpServiceStartName
))
!=
0
)
return
err
;
if
((
err
=
load_reg_string
(
hKey
,
SZ_DISPLAY_NAME
,
0
,
&
entry
->
config
.
lpDisplayName
))
!=
0
)
return
err
;
if
((
err
=
load_reg_string
(
hKey
,
SZ_DESCRIPTION
,
0
,
&
entry
->
description
))
!=
0
)
return
err
;
if
((
err
=
load_reg_multisz
(
hKey
,
SZ_DEPEND_ON_SERVICE
,
&
entry
->
dependOnServices
))
!=
0
)
return
err
;
if
((
err
=
load_reg_multisz
(
hKey
,
SZ_DEPEND_ON_GROUP
,
&
entry
->
dependOnGroups
))
!=
0
)
return
err
;
if
((
err
=
load_reg_dword
(
hKey
,
SZ_TYPE
,
&
entry
->
config
.
dwServiceType
))
!=
0
)
return
err
;
if
((
err
=
load_reg_dword
(
hKey
,
SZ_START
,
&
entry
->
config
.
dwStartType
))
!=
0
)
return
err
;
if
((
err
=
load_reg_dword
(
hKey
,
SZ_ERROR
,
&
entry
->
config
.
dwErrorControl
))
!=
0
)
return
err
;
if
((
err
=
load_reg_dword
(
hKey
,
SZ_TAG
,
&
entry
->
config
.
dwTagId
))
!=
0
)
return
err
;
WINE_TRACE
(
"Image path = %s
\n
"
,
wine_dbgstr_w
(
entry
->
config
.
lpBinaryPathName
)
);
WINE_TRACE
(
"Group = %s
\n
"
,
wine_dbgstr_w
(
entry
->
config
.
lpLoadOrderGroup
)
);
WINE_TRACE
(
"Service account name = %s
\n
"
,
wine_dbgstr_w
(
entry
->
config
.
lpServiceStartName
)
);
WINE_TRACE
(
"Display name = %s
\n
"
,
wine_dbgstr_w
(
entry
->
config
.
lpDisplayName
)
);
WINE_TRACE
(
"Service dependancies : %s
\n
"
,
entry
->
dependOnServices
[
0
]
?
""
:
"(none)"
);
for
(
wptr
=
entry
->
dependOnServices
;
*
wptr
;
wptr
+=
strlenW
(
wptr
)
+
1
)
WINE_TRACE
(
" * %s
\n
"
,
wine_dbgstr_w
(
wptr
));
WINE_TRACE
(
"Group dependancies : %s
\n
"
,
entry
->
dependOnGroups
[
0
]
?
""
:
"(none)"
);
for
(
wptr
=
entry
->
dependOnGroups
;
*
wptr
;
wptr
+=
strlenW
(
wptr
)
+
1
)
WINE_TRACE
(
" * %s
\n
"
,
wine_dbgstr_w
(
wptr
));
return
ERROR_SUCCESS
;
}
static
BOOL
validate_service_config
(
struct
service_entry
*
entry
)
{
if
(
entry
->
config
.
dwServiceType
&
SERVICE_WIN32
&&
(
entry
->
config
.
lpBinaryPathName
==
NULL
||
!
entry
->
config
.
lpBinaryPathName
[
0
]))
{
WINE_ERR
(
"Service %s is Win32 but have no image path set
\n
"
,
wine_dbgstr_w
(
entry
->
name
));
return
FALSE
;
}
return
TRUE
;
}
static
DWORD
load_services
(
void
)
{
HKEY
hServicesRootKey
;
DWORD
err
;
int
i
;
if
((
err
=
RegCreateKeyExW
(
HKEY_LOCAL_MACHINE
,
SZ_SERVICES_KEY
,
0
,
NULL
,
REG_OPTION_NON_VOLATILE
,
KEY_READ
,
NULL
,
&
hServicesRootKey
,
NULL
))
!=
ERROR_SUCCESS
)
{
WINE_ERR
(
"Couldn't open services key
\n
"
);
return
err
;
}
for
(
i
=
0
;
TRUE
;
i
++
)
{
WCHAR
szName
[
MAX_SERVICE_NAME
];
struct
service_entry
*
entry
;
HKEY
hServiceKey
;
err
=
RegEnumKeyW
(
hServicesRootKey
,
i
,
szName
,
MAX_SERVICE_NAME
);
if
(
err
==
ERROR_NO_MORE_ITEMS
)
break
;
if
(
err
!=
0
)
{
WINE_ERR
(
"Error %d reading key %d name - skipping
\n
"
,
err
,
i
);
continue
;
}
entry
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
*
entry
));
entry
->
name
=
strdupW
(
szName
);
WINE_TRACE
(
"Loading service %s
\n
"
,
wine_dbgstr_w
(
szName
));
err
=
RegOpenKeyExW
(
hServicesRootKey
,
szName
,
0
,
KEY_READ
|
KEY_WRITE
,
&
hServiceKey
);
if
(
err
==
ERROR_SUCCESS
)
{
err
=
load_service_config
(
hServiceKey
,
entry
);
RegCloseKey
(
hServiceKey
);
}
if
(
err
!=
ERROR_SUCCESS
)
{
WINE_ERR
(
"Error %d reading registry key for service %s - skipping
\n
"
,
err
,
wine_dbgstr_w
(
szName
));
free_service_entry
(
entry
);
continue
;
}
if
(
entry
->
config
.
dwServiceType
==
0
)
{
/* Maybe an application only wrote some configuration in the service key. Continue silently */
WINE_TRACE
(
"Even the service type not set for service %s - skipping
\n
"
,
wine_dbgstr_w
(
szName
));
free_service_entry
(
entry
);
continue
;
}
if
(
!
validate_service_config
(
entry
))
{
WINE_ERR
(
"Invalid configuration of service %s - skipping
\n
"
,
wine_dbgstr_w
(
szName
));
free_service_entry
(
entry
);
continue
;
}
entry
->
status
.
dwServiceType
=
entry
->
config
.
dwServiceType
;
entry
->
status
.
dwCurrentState
=
SERVICE_STOPPED
;
entry
->
status
.
dwWin32ExitCode
=
ERROR_SERVICE_NEVER_STARTED
;
/* all other fields are zero */
list_add_tail
(
&
g_services
,
&
entry
->
entry
);
}
RegCloseKey
(
hServicesRootKey
);
return
ERROR_SUCCESS
;
}
int
main
(
int
argc
,
char
*
argv
[])
{
DWORD
err
;
list_init
(
&
g_services
);
if
((
err
=
load_services
())
!=
ERROR_SUCCESS
)
return
err
;
return
0
;
}
programs/services/services.h
0 → 100644
View file @
a1fbd550
/*
* Services.exe - include file
*
* Copyright 2007 Google (Mikolaj Zalewski)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#ifndef WINE_PROGRAMS_UTILS_H_
#define WINE_PROGRAMS_UTILS_H_
#include "wine/list.h"
struct
service_entry
{
struct
list
entry
;
LPWSTR
name
;
SERVICE_STATUS_PROCESS
status
;
QUERY_SERVICE_CONFIGW
config
;
LPWSTR
description
;
LPWSTR
dependOnServices
;
LPWSTR
dependOnGroups
;
};
extern
HANDLE
g_hStartedEvent
;
DWORD
RPC_MainLoop
(
void
);
/* from utils.c */
LPWSTR
strdupW
(
LPCWSTR
str
);
DWORD
load_reg_string
(
HKEY
hKey
,
LPCWSTR
szValue
,
BOOL
bExpand
,
LPWSTR
*
output
);
DWORD
load_reg_multisz
(
HKEY
hKey
,
LPCWSTR
szValue
,
LPWSTR
*
output
);
DWORD
load_reg_dword
(
HKEY
hKey
,
LPCWSTR
szValue
,
DWORD
*
output
);
#endif
/*WINE_PROGRAMS_UTILS_H_*/
programs/services/utils.c
0 → 100644
View file @
a1fbd550
/*
* Services.exe - some utility functions
*
* Copyright 2007 Google (Mikolaj Zalewski)
*
* This library is free software; you can redistribute it and/or
* modify it under the terms of the GNU Lesser General Public
* License as published by the Free Software Foundation; either
* version 2.1 of the License, or (at your option) any later version.
*
* This library is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
* Lesser General Public License for more details.
*
* You should have received a copy of the GNU Lesser General Public
* License along with this library; if not, write to the Free Software
* Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301, USA
*/
#define WIN32_LEAN_AND_MEAN
#include <stdarg.h>
#include <windows.h>
#include "wine/unicode.h"
#include "wine/debug.h"
#include "services.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
service
);
LPWSTR
strdupW
(
LPCWSTR
str
)
{
int
len
=
strlenW
(
str
);
WCHAR
*
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
WCHAR
)
*
(
len
+
1
));
if
(
buf
==
NULL
)
return
NULL
;
strcpyW
(
buf
,
str
);
return
buf
;
}
DWORD
load_reg_string
(
HKEY
hKey
,
LPCWSTR
szValue
,
BOOL
bExpand
,
LPWSTR
*
output
)
{
DWORD
size
,
type
;
LPWSTR
buf
=
NULL
;
DWORD
err
;
*
output
=
NULL
;
if
((
err
=
RegQueryValueExW
(
hKey
,
szValue
,
0
,
&
type
,
NULL
,
&
size
))
!=
0
)
{
if
(
err
==
ERROR_FILE_NOT_FOUND
)
return
ERROR_SUCCESS
;
goto
failed
;
}
if
(
!
(
type
==
REG_SZ
||
(
type
==
REG_EXPAND_SZ
&&
bExpand
)))
{
err
=
ERROR_INVALID_DATATYPE
;
goto
failed
;
}
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
+
sizeof
(
WCHAR
));
if
((
err
=
RegQueryValueExW
(
hKey
,
szValue
,
0
,
&
type
,
(
LPBYTE
)
buf
,
&
size
))
!=
0
)
goto
failed
;
buf
[
size
/
sizeof
(
WCHAR
)]
=
0
;
if
(
type
==
REG_EXPAND_SZ
)
{
LPWSTR
str
;
DWORD
size
=
ExpandEnvironmentStringsW
(
buf
,
NULL
,
0
);
if
(
size
==
0
)
{
err
=
GetLastError
();
goto
failed
;
}
str
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
*
sizeof
(
WCHAR
));
ExpandEnvironmentStringsW
(
buf
,
str
,
size
);
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
*
output
=
str
;
}
else
*
output
=
buf
;
return
ERROR_SUCCESS
;
failed:
WINE_ERR
(
"Error %d while reading value %s
\n
"
,
err
,
wine_dbgstr_w
(
szValue
));
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
return
err
;
}
DWORD
load_reg_multisz
(
HKEY
hKey
,
LPCWSTR
szValue
,
LPWSTR
*
output
)
{
DWORD
size
,
type
;
LPWSTR
buf
=
NULL
;
DWORD
err
;
*
output
=
NULL
;
if
((
err
=
RegQueryValueExW
(
hKey
,
szValue
,
0
,
&
type
,
NULL
,
&
size
))
!=
0
)
{
if
(
err
==
ERROR_FILE_NOT_FOUND
)
{
*
output
=
HeapAlloc
(
GetProcessHeap
(),
HEAP_ZERO_MEMORY
,
sizeof
(
WCHAR
));
return
ERROR_SUCCESS
;
}
goto
failed
;
}
if
(
type
!=
REG_MULTI_SZ
)
{
err
=
ERROR_INVALID_DATATYPE
;
goto
failed
;
}
buf
=
HeapAlloc
(
GetProcessHeap
(),
0
,
size
+
2
*
sizeof
(
WCHAR
));
if
((
err
=
RegQueryValueExW
(
hKey
,
szValue
,
0
,
&
type
,
(
LPBYTE
)
buf
,
&
size
))
!=
0
)
goto
failed
;
buf
[
size
/
sizeof
(
WCHAR
)]
=
0
;
buf
[
size
/
sizeof
(
WCHAR
)
+
1
]
=
0
;
*
output
=
buf
;
return
ERROR_SUCCESS
;
failed:
WINE_ERR
(
"Error %d while reading value %s
\n
"
,
err
,
wine_dbgstr_w
(
szValue
));
HeapFree
(
GetProcessHeap
(),
0
,
buf
);
return
err
;
}
DWORD
load_reg_dword
(
HKEY
hKey
,
LPCWSTR
szValue
,
DWORD
*
output
)
{
DWORD
size
,
type
;
DWORD
err
;
*
output
=
0
;
size
=
sizeof
(
DWORD
);
if
((
err
=
RegQueryValueExW
(
hKey
,
szValue
,
0
,
&
type
,
(
LPBYTE
)
output
,
&
size
))
!=
0
)
{
if
(
err
==
ERROR_FILE_NOT_FOUND
)
return
ERROR_SUCCESS
;
goto
failed
;
}
if
(
type
!=
REG_DWORD
||
size
!=
sizeof
(
DWORD
))
{
err
=
ERROR_INVALID_DATATYPE
;
goto
failed
;
}
return
ERROR_SUCCESS
;
failed:
WINE_ERR
(
"Error %d while reading value %s
\n
"
,
err
,
wine_dbgstr_w
(
szValue
));
return
err
;
}
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