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
97bc30ae
Commit
97bc30ae
authored
Nov 12, 2013
by
Hans Leidekker
Committed by
Alexandre Julliard
Nov 12, 2013
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
netapi32: Merge access.c into netapi32.c.
parent
cf597a76
Hide whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
1002 additions
and
1048 deletions
+1002
-1048
Makefile.in
dlls/netapi32/Makefile.in
+0
-1
access.c
dlls/netapi32/access.c
+0
-1047
netapi32.c
dlls/netapi32/netapi32.c
+1002
-0
No files found.
dlls/netapi32/Makefile.in
View file @
97bc30ae
...
...
@@ -4,7 +4,6 @@ IMPORTLIB = netapi32
IMPORTS
=
iphlpapi ws2_32 advapi32
C_SRCS
=
\
access.c
\
browsr.c
\
ds.c
\
local_group.c
\
...
...
dlls/netapi32/access.c
deleted
100644 → 0
View file @
cf597a76
/*
* Copyright 2002 Andriy Palamarchuk
*
* netapi32 access functions
*
* 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
*/
#include "config.h"
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "winerror.h"
#include "lmcons.h"
#include "lmaccess.h"
#include "lmapibuf.h"
#include "lmerr.h"
#include "lmuse.h"
#include "ntsecapi.h"
#include "wine/debug.h"
#include "wine/unicode.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
netapi32
);
/* NOTE: So far, this is implemented to support tests that require user logins,
* but not designed to handle real user databases. Those should probably
* be synced with either the host's user database or with Samba.
*
* FIXME: The user database should hold all the information the USER_INFO_4 struct
* needs, but for the first try, I will just implement the USER_INFO_1 fields.
*/
struct
sam_user
{
struct
list
entry
;
WCHAR
user_name
[
LM20_UNLEN
+
1
];
WCHAR
user_password
[
PWLEN
+
1
];
DWORD
sec_since_passwd_change
;
DWORD
user_priv
;
LPWSTR
home_dir
;
LPWSTR
user_comment
;
DWORD
user_flags
;
LPWSTR
user_logon_script_path
;
};
static
struct
list
user_list
=
LIST_INIT
(
user_list
);
BOOL
NETAPI_IsLocalComputer
(
LPCWSTR
ServerName
);
/************************************************************
* NETAPI_ValidateServername
*
* Validates server name
*/
static
NET_API_STATUS
NETAPI_ValidateServername
(
LPCWSTR
ServerName
)
{
if
(
ServerName
)
{
if
(
ServerName
[
0
]
==
0
)
return
ERROR_BAD_NETPATH
;
else
if
(
((
ServerName
[
0
]
==
'\\'
)
&&
(
ServerName
[
1
]
!=
'\\'
))
||
((
ServerName
[
0
]
==
'\\'
)
&&
(
ServerName
[
1
]
==
'\\'
)
&&
(
ServerName
[
2
]
==
0
))
)
return
ERROR_INVALID_NAME
;
}
return
NERR_Success
;
}
/************************************************************
* NETAPI_FindUser
*
* Looks for a user in the user database.
* Returns a pointer to the entry in the user list when the user
* is found, NULL otherwise.
*/
static
struct
sam_user
*
NETAPI_FindUser
(
LPCWSTR
UserName
)
{
struct
sam_user
*
user
;
LIST_FOR_EACH_ENTRY
(
user
,
&
user_list
,
struct
sam_user
,
entry
)
{
if
(
lstrcmpW
(
user
->
user_name
,
UserName
)
==
0
)
return
user
;
}
return
NULL
;
}
static
BOOL
NETAPI_IsCurrentUser
(
LPCWSTR
username
)
{
LPWSTR
curr_user
=
NULL
;
DWORD
dwSize
;
BOOL
ret
=
FALSE
;
dwSize
=
LM20_UNLEN
+
1
;
curr_user
=
HeapAlloc
(
GetProcessHeap
(),
0
,
dwSize
*
sizeof
(
WCHAR
));
if
(
!
curr_user
)
{
ERR
(
"Failed to allocate memory for user name.
\n
"
);
goto
end
;
}
if
(
!
GetUserNameW
(
curr_user
,
&
dwSize
))
{
ERR
(
"Failed to get current user's user name.
\n
"
);
goto
end
;
}
if
(
!
lstrcmpW
(
curr_user
,
username
))
{
ret
=
TRUE
;
}
end:
HeapFree
(
GetProcessHeap
(),
0
,
curr_user
);
return
ret
;
}
/************************************************************
* NetUserAdd (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserAdd
(
LPCWSTR
servername
,
DWORD
level
,
LPBYTE
bufptr
,
LPDWORD
parm_err
)
{
NET_API_STATUS
status
;
struct
sam_user
*
su
=
NULL
;
FIXME
(
"(%s, %d, %p, %p) stub!
\n
"
,
debugstr_w
(
servername
),
level
,
bufptr
,
parm_err
);
if
((
status
=
NETAPI_ValidateServername
(
servername
))
!=
NERR_Success
)
return
status
;
switch
(
level
)
{
/* Level 3 and 4 are identical for the purposes of NetUserAdd */
case
4
:
case
3
:
FIXME
(
"Level 3 and 4 not implemented.
\n
"
);
/* Fall through */
case
2
:
FIXME
(
"Level 2 not implemented.
\n
"
);
/* Fall through */
case
1
:
{
PUSER_INFO_1
ui
=
(
PUSER_INFO_1
)
bufptr
;
su
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
struct
sam_user
));
if
(
!
su
)
{
status
=
NERR_InternalError
;
break
;
}
if
(
lstrlenW
(
ui
->
usri1_name
)
>
LM20_UNLEN
)
{
status
=
NERR_BadUsername
;
break
;
}
/*FIXME: do other checks for a valid username */
lstrcpyW
(
su
->
user_name
,
ui
->
usri1_name
);
if
(
lstrlenW
(
ui
->
usri1_password
)
>
PWLEN
)
{
/* Always return PasswordTooShort on invalid passwords. */
status
=
NERR_PasswordTooShort
;
break
;
}
lstrcpyW
(
su
->
user_password
,
ui
->
usri1_password
);
su
->
sec_since_passwd_change
=
ui
->
usri1_password_age
;
su
->
user_priv
=
ui
->
usri1_priv
;
su
->
user_flags
=
ui
->
usri1_flags
;
/*FIXME: set the other LPWSTRs to NULL for now */
su
->
home_dir
=
NULL
;
su
->
user_comment
=
NULL
;
su
->
user_logon_script_path
=
NULL
;
list_add_head
(
&
user_list
,
&
su
->
entry
);
return
NERR_Success
;
}
default:
TRACE
(
"Invalid level %d specified.
\n
"
,
level
);
status
=
ERROR_INVALID_LEVEL
;
break
;
}
HeapFree
(
GetProcessHeap
(),
0
,
su
);
return
status
;
}
/************************************************************
* NetUserDel (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserDel
(
LPCWSTR
servername
,
LPCWSTR
username
)
{
NET_API_STATUS
status
;
struct
sam_user
*
user
;
TRACE
(
"(%s, %s)
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
username
));
if
((
status
=
NETAPI_ValidateServername
(
servername
))
!=
NERR_Success
)
return
status
;
if
((
user
=
NETAPI_FindUser
(
username
))
==
NULL
)
return
NERR_UserNotFound
;
list_remove
(
&
user
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
user
->
home_dir
);
HeapFree
(
GetProcessHeap
(),
0
,
user
->
user_comment
);
HeapFree
(
GetProcessHeap
(),
0
,
user
->
user_logon_script_path
);
HeapFree
(
GetProcessHeap
(),
0
,
user
);
return
NERR_Success
;
}
/************************************************************
* NetUserGetInfo (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserGetInfo
(
LPCWSTR
servername
,
LPCWSTR
username
,
DWORD
level
,
LPBYTE
*
bufptr
)
{
NET_API_STATUS
status
;
TRACE
(
"(%s, %s, %d, %p)
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
username
),
level
,
bufptr
);
status
=
NETAPI_ValidateServername
(
servername
);
if
(
status
!=
NERR_Success
)
return
status
;
if
(
!
NETAPI_IsLocalComputer
(
servername
))
{
FIXME
(
"Only implemented for local computer, but remote server"
"%s was requested.
\n
"
,
debugstr_w
(
servername
));
return
NERR_InvalidComputer
;
}
if
(
!
NETAPI_FindUser
(
username
)
&&
!
NETAPI_IsCurrentUser
(
username
))
{
TRACE
(
"User %s is unknown.
\n
"
,
debugstr_w
(
username
));
return
NERR_UserNotFound
;
}
switch
(
level
)
{
case
0
:
{
PUSER_INFO_0
ui
;
int
name_sz
;
name_sz
=
lstrlenW
(
username
)
+
1
;
/* set up buffer */
NetApiBufferAllocate
(
sizeof
(
USER_INFO_0
)
+
name_sz
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
bufptr
);
ui
=
(
PUSER_INFO_0
)
*
bufptr
;
ui
->
usri0_name
=
(
LPWSTR
)
(
*
bufptr
+
sizeof
(
USER_INFO_0
));
/* get data */
lstrcpyW
(
ui
->
usri0_name
,
username
);
break
;
}
case
10
:
{
PUSER_INFO_10
ui
;
PUSER_INFO_0
ui0
;
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
usr_comment_sz
,
full_name_sz
;
comment_sz
=
1
;
usr_comment_sz
=
1
;
full_name_sz
=
1
;
/* get data */
status
=
NetUserGetInfo
(
servername
,
username
,
0
,
(
LPBYTE
*
)
&
ui0
);
if
(
status
!=
NERR_Success
)
{
NetApiBufferFree
(
ui0
);
return
status
;
}
name_sz
=
lstrlenW
(
ui0
->
usri0_name
)
+
1
;
/* set up buffer */
NetApiBufferAllocate
(
sizeof
(
USER_INFO_10
)
+
(
name_sz
+
comment_sz
+
usr_comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
bufptr
);
ui
=
(
PUSER_INFO_10
)
*
bufptr
;
ui
->
usri10_name
=
(
LPWSTR
)
(
*
bufptr
+
sizeof
(
USER_INFO_10
));
ui
->
usri10_comment
=
(
LPWSTR
)
(
((
PBYTE
)
ui
->
usri10_name
)
+
name_sz
*
sizeof
(
WCHAR
));
ui
->
usri10_usr_comment
=
(
LPWSTR
)
(
((
PBYTE
)
ui
->
usri10_comment
)
+
comment_sz
*
sizeof
(
WCHAR
));
ui
->
usri10_full_name
=
(
LPWSTR
)
(
((
PBYTE
)
ui
->
usri10_usr_comment
)
+
usr_comment_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
ui
->
usri10_name
,
ui0
->
usri0_name
);
NetApiBufferFree
(
ui0
);
ui
->
usri10_comment
[
0
]
=
0
;
ui
->
usri10_usr_comment
[
0
]
=
0
;
ui
->
usri10_full_name
[
0
]
=
0
;
break
;
}
case
1
:
{
static
const
WCHAR
homedirW
[]
=
{
'H'
,
'O'
,
'M'
,
'E'
,
0
};
PUSER_INFO_1
ui
;
PUSER_INFO_0
ui0
;
/* sizes of the field buffers in WCHARS */
int
name_sz
,
password_sz
,
home_dir_sz
,
comment_sz
,
script_path_sz
;
password_sz
=
1
;
/* not filled out for security reasons for NetUserGetInfo*/
comment_sz
=
1
;
script_path_sz
=
1
;
/* get data */
status
=
NetUserGetInfo
(
servername
,
username
,
0
,
(
LPBYTE
*
)
&
ui0
);
if
(
status
!=
NERR_Success
)
{
NetApiBufferFree
(
ui0
);
return
status
;
}
name_sz
=
lstrlenW
(
ui0
->
usri0_name
)
+
1
;
home_dir_sz
=
GetEnvironmentVariableW
(
homedirW
,
NULL
,
0
);
/* set up buffer */
NetApiBufferAllocate
(
sizeof
(
USER_INFO_1
)
+
(
name_sz
+
password_sz
+
home_dir_sz
+
comment_sz
+
script_path_sz
)
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
bufptr
);
ui
=
(
PUSER_INFO_1
)
*
bufptr
;
ui
->
usri1_name
=
(
LPWSTR
)
(
ui
+
1
);
ui
->
usri1_password
=
ui
->
usri1_name
+
name_sz
;
ui
->
usri1_home_dir
=
ui
->
usri1_password
+
password_sz
;
ui
->
usri1_comment
=
ui
->
usri1_home_dir
+
home_dir_sz
;
ui
->
usri1_script_path
=
ui
->
usri1_comment
+
comment_sz
;
/* set data */
lstrcpyW
(
ui
->
usri1_name
,
ui0
->
usri0_name
);
NetApiBufferFree
(
ui0
);
ui
->
usri1_password
[
0
]
=
0
;
ui
->
usri1_password_age
=
0
;
ui
->
usri1_priv
=
0
;
GetEnvironmentVariableW
(
homedirW
,
ui
->
usri1_home_dir
,
home_dir_sz
);
ui
->
usri1_comment
[
0
]
=
0
;
ui
->
usri1_flags
=
0
;
ui
->
usri1_script_path
[
0
]
=
0
;
break
;
}
case
2
:
case
3
:
case
4
:
case
11
:
case
20
:
case
23
:
case
1003
:
case
1005
:
case
1006
:
case
1007
:
case
1008
:
case
1009
:
case
1010
:
case
1011
:
case
1012
:
case
1013
:
case
1014
:
case
1017
:
case
1018
:
case
1020
:
case
1023
:
case
1024
:
case
1025
:
case
1051
:
case
1052
:
case
1053
:
{
FIXME
(
"Level %d is not implemented
\n
"
,
level
);
return
NERR_InternalError
;
}
default:
TRACE
(
"Invalid level %d is specified
\n
"
,
level
);
return
ERROR_INVALID_LEVEL
;
}
return
NERR_Success
;
}
/************************************************************
* NetUserGetLocalGroups (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserGetLocalGroups
(
LPCWSTR
servername
,
LPCWSTR
username
,
DWORD
level
,
DWORD
flags
,
LPBYTE
*
bufptr
,
DWORD
prefmaxlen
,
LPDWORD
entriesread
,
LPDWORD
totalentries
)
{
NET_API_STATUS
status
;
const
WCHAR
admins
[]
=
{
'A'
,
'd'
,
'm'
,
'i'
,
'n'
,
'i'
,
's'
,
't'
,
'r'
,
'a'
,
't'
,
'o'
,
'r'
,
's'
,
0
};
LPWSTR
currentuser
;
LOCALGROUP_USERS_INFO_0
*
info
;
DWORD
size
;
FIXME
(
"(%s, %s, %d, %08x, %p %d, %p, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
username
),
level
,
flags
,
bufptr
,
prefmaxlen
,
entriesread
,
totalentries
);
status
=
NETAPI_ValidateServername
(
servername
);
if
(
status
!=
NERR_Success
)
return
status
;
size
=
UNLEN
+
1
;
NetApiBufferAllocate
(
size
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
&
currentuser
);
if
(
!
GetUserNameW
(
currentuser
,
&
size
))
{
NetApiBufferFree
(
currentuser
);
return
ERROR_NOT_ENOUGH_MEMORY
;
}
if
(
lstrcmpiW
(
username
,
currentuser
)
&&
NETAPI_FindUser
(
username
))
{
NetApiBufferFree
(
currentuser
);
return
NERR_UserNotFound
;
}
NetApiBufferFree
(
currentuser
);
*
totalentries
=
1
;
size
=
sizeof
(
*
info
)
+
sizeof
(
admins
);
if
(
prefmaxlen
<
size
)
status
=
ERROR_MORE_DATA
;
else
status
=
NetApiBufferAllocate
(
size
,
(
LPVOID
*
)
&
info
);
if
(
status
!=
NERR_Success
)
{
*
bufptr
=
NULL
;
*
entriesread
=
0
;
return
status
;
}
info
->
lgrui0_name
=
(
LPWSTR
)((
LPBYTE
)
info
+
sizeof
(
*
info
));
lstrcpyW
(
info
->
lgrui0_name
,
admins
);
*
bufptr
=
(
LPBYTE
)
info
;
*
entriesread
=
1
;
return
NERR_Success
;
}
/************************************************************
* NetUserEnum (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserEnum
(
LPCWSTR
servername
,
DWORD
level
,
DWORD
filter
,
LPBYTE
*
bufptr
,
DWORD
prefmaxlen
,
LPDWORD
entriesread
,
LPDWORD
totalentries
,
LPDWORD
resume_handle
)
{
FIXME
(
"(%s,%d, 0x%d,%p,%d,%p,%p,%p) stub!
\n
"
,
debugstr_w
(
servername
),
level
,
filter
,
bufptr
,
prefmaxlen
,
entriesread
,
totalentries
,
resume_handle
);
return
ERROR_ACCESS_DENIED
;
}
/************************************************************
* ACCESS_QueryAdminDisplayInformation
*
* Creates a buffer with information for the Admin User
*/
static
void
ACCESS_QueryAdminDisplayInformation
(
PNET_DISPLAY_USER
*
buf
,
PDWORD
pdwSize
)
{
static
const
WCHAR
sAdminUserName
[]
=
{
'A'
,
'd'
,
'm'
,
'i'
,
'n'
,
'i'
,
's'
,
't'
,
'r'
,
'a'
,
't'
,
'o'
,
'r'
,
0
};
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
full_name_sz
;
PNET_DISPLAY_USER
usr
;
/* set up buffer */
name_sz
=
lstrlenW
(
sAdminUserName
)
+
1
;
comment_sz
=
1
;
full_name_sz
=
1
;
*
pdwSize
=
sizeof
(
NET_DISPLAY_USER
);
*
pdwSize
+=
(
name_sz
+
comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
);
NetApiBufferAllocate
(
*
pdwSize
,
(
LPVOID
*
)
buf
);
usr
=
*
buf
;
usr
->
usri1_name
=
(
LPWSTR
)
((
PBYTE
)
usr
+
sizeof
(
NET_DISPLAY_USER
));
usr
->
usri1_comment
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_name
)
+
name_sz
*
sizeof
(
WCHAR
));
usr
->
usri1_full_name
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_comment
)
+
comment_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
usr
->
usri1_name
,
sAdminUserName
);
usr
->
usri1_comment
[
0
]
=
0
;
usr
->
usri1_flags
=
UF_SCRIPT
|
UF_NORMAL_ACCOUNT
|
UF_DONT_EXPIRE_PASSWD
;
usr
->
usri1_full_name
[
0
]
=
0
;
usr
->
usri1_user_id
=
DOMAIN_USER_RID_ADMIN
;
usr
->
usri1_next_index
=
0
;
}
/************************************************************
* ACCESS_QueryGuestDisplayInformation
*
* Creates a buffer with information for the Guest User
*/
static
void
ACCESS_QueryGuestDisplayInformation
(
PNET_DISPLAY_USER
*
buf
,
PDWORD
pdwSize
)
{
static
const
WCHAR
sGuestUserName
[]
=
{
'G'
,
'u'
,
'e'
,
's'
,
't'
,
0
};
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
full_name_sz
;
PNET_DISPLAY_USER
usr
;
/* set up buffer */
name_sz
=
lstrlenW
(
sGuestUserName
)
+
1
;
comment_sz
=
1
;
full_name_sz
=
1
;
*
pdwSize
=
sizeof
(
NET_DISPLAY_USER
);
*
pdwSize
+=
(
name_sz
+
comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
);
NetApiBufferAllocate
(
*
pdwSize
,
(
LPVOID
*
)
buf
);
usr
=
*
buf
;
usr
->
usri1_name
=
(
LPWSTR
)
((
PBYTE
)
usr
+
sizeof
(
NET_DISPLAY_USER
));
usr
->
usri1_comment
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_name
)
+
name_sz
*
sizeof
(
WCHAR
));
usr
->
usri1_full_name
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_comment
)
+
comment_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
usr
->
usri1_name
,
sGuestUserName
);
usr
->
usri1_comment
[
0
]
=
0
;
usr
->
usri1_flags
=
UF_ACCOUNTDISABLE
|
UF_SCRIPT
|
UF_NORMAL_ACCOUNT
|
UF_DONT_EXPIRE_PASSWD
;
usr
->
usri1_full_name
[
0
]
=
0
;
usr
->
usri1_user_id
=
DOMAIN_USER_RID_GUEST
;
usr
->
usri1_next_index
=
0
;
}
/************************************************************
* Copies NET_DISPLAY_USER record.
*/
static
void
ACCESS_CopyDisplayUser
(
const
NET_DISPLAY_USER
*
dest
,
LPWSTR
*
dest_buf
,
PNET_DISPLAY_USER
src
)
{
LPWSTR
str
=
*
dest_buf
;
src
->
usri1_name
=
str
;
lstrcpyW
(
src
->
usri1_name
,
dest
->
usri1_name
);
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
));
src
->
usri1_comment
=
str
;
lstrcpyW
(
src
->
usri1_comment
,
dest
->
usri1_comment
);
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
));
src
->
usri1_flags
=
dest
->
usri1_flags
;
src
->
usri1_full_name
=
str
;
lstrcpyW
(
src
->
usri1_full_name
,
dest
->
usri1_full_name
);
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
));
src
->
usri1_user_id
=
dest
->
usri1_user_id
;
src
->
usri1_next_index
=
dest
->
usri1_next_index
;
*
dest_buf
=
str
;
}
/************************************************************
* NetQueryDisplayInformation (NETAPI32.@)
*
* The buffer structure:
* - array of fixed size record of the level type
* - strings, referenced by the record of the level type
*/
NET_API_STATUS
WINAPI
NetQueryDisplayInformation
(
LPCWSTR
ServerName
,
DWORD
Level
,
DWORD
Index
,
DWORD
EntriesRequested
,
DWORD
PreferredMaximumLength
,
LPDWORD
ReturnedEntryCount
,
PVOID
*
SortedBuffer
)
{
TRACE
(
"(%s, %d, %d, %d, %d, %p, %p)
\n
"
,
debugstr_w
(
ServerName
),
Level
,
Index
,
EntriesRequested
,
PreferredMaximumLength
,
ReturnedEntryCount
,
SortedBuffer
);
if
(
!
NETAPI_IsLocalComputer
(
ServerName
))
{
FIXME
(
"Only implemented on local computer, but requested for "
"remote server %s
\n
"
,
debugstr_w
(
ServerName
));
return
ERROR_ACCESS_DENIED
;
}
switch
(
Level
)
{
case
1
:
{
/* current record */
PNET_DISPLAY_USER
inf
;
/* current available strings buffer */
LPWSTR
str
;
PNET_DISPLAY_USER
admin
,
guest
;
DWORD
admin_size
,
guest_size
;
LPWSTR
name
=
NULL
;
DWORD
dwSize
;
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
full_name_sz
;
/* number of the records, returned in SortedBuffer
3 - for current user, Administrator and Guest users
*/
int
records
=
3
;
FIXME
(
"Level %d partially implemented
\n
"
,
Level
);
*
ReturnedEntryCount
=
records
;
comment_sz
=
1
;
full_name_sz
=
1
;
/* get data */
dwSize
=
UNLEN
+
1
;
NetApiBufferAllocate
(
dwSize
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
&
name
);
if
(
!
GetUserNameW
(
name
,
&
dwSize
))
{
NetApiBufferFree
(
name
);
return
ERROR_ACCESS_DENIED
;
}
name_sz
=
dwSize
;
ACCESS_QueryAdminDisplayInformation
(
&
admin
,
&
admin_size
);
ACCESS_QueryGuestDisplayInformation
(
&
guest
,
&
guest_size
);
/* set up buffer */
dwSize
=
sizeof
(
NET_DISPLAY_USER
)
*
records
;
dwSize
+=
(
name_sz
+
comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
);
NetApiBufferAllocate
(
dwSize
+
admin_size
-
sizeof
(
NET_DISPLAY_USER
)
+
guest_size
-
sizeof
(
NET_DISPLAY_USER
),
SortedBuffer
);
inf
=
*
SortedBuffer
;
str
=
(
LPWSTR
)
((
PBYTE
)
inf
+
sizeof
(
NET_DISPLAY_USER
)
*
records
);
inf
->
usri1_name
=
str
;
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
name_sz
*
sizeof
(
WCHAR
));
inf
->
usri1_comment
=
str
;
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
comment_sz
*
sizeof
(
WCHAR
));
inf
->
usri1_full_name
=
str
;
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
full_name_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
inf
->
usri1_name
,
name
);
NetApiBufferFree
(
name
);
inf
->
usri1_comment
[
0
]
=
0
;
inf
->
usri1_flags
=
UF_SCRIPT
|
UF_NORMAL_ACCOUNT
|
UF_DONT_EXPIRE_PASSWD
;
inf
->
usri1_full_name
[
0
]
=
0
;
inf
->
usri1_user_id
=
0
;
inf
->
usri1_next_index
=
0
;
inf
++
;
ACCESS_CopyDisplayUser
(
admin
,
&
str
,
inf
);
NetApiBufferFree
(
admin
);
inf
++
;
ACCESS_CopyDisplayUser
(
guest
,
&
str
,
inf
);
NetApiBufferFree
(
guest
);
break
;
}
case
2
:
case
3
:
{
FIXME
(
"Level %d is not implemented
\n
"
,
Level
);
break
;
}
default:
TRACE
(
"Invalid level %d is specified
\n
"
,
Level
);
return
ERROR_INVALID_LEVEL
;
}
return
NERR_Success
;
}
/************************************************************
* NetGetDCName (NETAPI32.@)
*
* Return the name of the primary domain controller (PDC)
*/
NET_API_STATUS
WINAPI
NetGetDCName
(
LPCWSTR
servername
,
LPCWSTR
domainname
,
LPBYTE
*
bufptr
)
{
FIXME
(
"(%s, %s, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
domainname
),
bufptr
);
return
NERR_DCNotFound
;
/* say we can't find a domain controller */
}
/************************************************************
* NetGetAnyDCName (NETAPI32.@)
*
* Return the name of any domain controller (DC) for a
* domain that is directly trusted by the specified server
*/
NET_API_STATUS
WINAPI
NetGetAnyDCName
(
LPCWSTR
servername
,
LPCWSTR
domainname
,
LPBYTE
*
bufptr
)
{
FIXME
(
"(%s, %s, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
domainname
),
bufptr
);
return
ERROR_NO_SUCH_DOMAIN
;
}
/************************************************************
* NetGroupEnum (NETAPI32.@)
*
*/
NET_API_STATUS
WINAPI
NetGroupEnum
(
LPCWSTR
servername
,
DWORD
level
,
LPBYTE
*
bufptr
,
DWORD
prefmaxlen
,
LPDWORD
entriesread
,
LPDWORD
totalentries
,
LPDWORD
resume_handle
)
{
FIXME
(
"(%s, %d, %p, %d, %p, %p, %p) stub!
\n
"
,
debugstr_w
(
servername
),
level
,
bufptr
,
prefmaxlen
,
entriesread
,
totalentries
,
resume_handle
);
return
ERROR_ACCESS_DENIED
;
}
/************************************************************
* NetGroupGetInfo (NETAPI32.@)
*
*/
NET_API_STATUS
WINAPI
NetGroupGetInfo
(
LPCWSTR
servername
,
LPCWSTR
groupname
,
DWORD
level
,
LPBYTE
*
bufptr
)
{
FIXME
(
"(%s, %s, %d, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
groupname
),
level
,
bufptr
);
return
ERROR_ACCESS_DENIED
;
}
/******************************************************************************
* NetUserModalsGet (NETAPI32.@)
*
* Retrieves global information for all users and global groups in the security
* database.
*
* PARAMS
* szServer [I] Specifies the DNS or the NetBIOS name of the remote server
* on which the function is to execute.
* level [I] Information level of the data.
* 0 Return global passwords parameters. bufptr points to a
* USER_MODALS_INFO_0 struct.
* 1 Return logon server and domain controller information. bufptr
* points to a USER_MODALS_INFO_1 struct.
* 2 Return domain name and identifier. bufptr points to a
* USER_MODALS_INFO_2 struct.
* 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
* struct.
* pbuffer [I] Buffer that receives the data.
*
* RETURNS
* Success: NERR_Success.
* Failure:
* ERROR_ACCESS_DENIED - the user does not have access to the info.
* NERR_InvalidComputer - computer name is invalid.
*/
NET_API_STATUS
WINAPI
NetUserModalsGet
(
LPCWSTR
szServer
,
DWORD
level
,
LPBYTE
*
pbuffer
)
{
TRACE
(
"(%s %d %p)
\n
"
,
debugstr_w
(
szServer
),
level
,
pbuffer
);
switch
(
level
)
{
case
0
:
/* return global passwords parameters */
FIXME
(
"level 0 not implemented!
\n
"
);
*
pbuffer
=
NULL
;
return
NERR_InternalError
;
case
1
:
/* return logon server and domain controller info */
FIXME
(
"level 1 not implemented!
\n
"
);
*
pbuffer
=
NULL
;
return
NERR_InternalError
;
case
2
:
{
/* return domain name and identifier */
PUSER_MODALS_INFO_2
umi
;
LSA_HANDLE
policyHandle
;
LSA_OBJECT_ATTRIBUTES
objectAttributes
;
PPOLICY_ACCOUNT_DOMAIN_INFO
domainInfo
;
NTSTATUS
ntStatus
;
PSID
domainIdentifier
=
NULL
;
int
domainNameLen
;
ZeroMemory
(
&
objectAttributes
,
sizeof
(
objectAttributes
));
objectAttributes
.
Length
=
sizeof
(
objectAttributes
);
ntStatus
=
LsaOpenPolicy
(
NULL
,
&
objectAttributes
,
POLICY_VIEW_LOCAL_INFORMATION
,
&
policyHandle
);
if
(
ntStatus
!=
STATUS_SUCCESS
)
{
WARN
(
"LsaOpenPolicy failed with NT status %x
\n
"
,
LsaNtStatusToWinError
(
ntStatus
));
return
ntStatus
;
}
ntStatus
=
LsaQueryInformationPolicy
(
policyHandle
,
PolicyAccountDomainInformation
,
(
PVOID
*
)
&
domainInfo
);
if
(
ntStatus
!=
STATUS_SUCCESS
)
{
WARN
(
"LsaQueryInformationPolicy failed with NT status %x
\n
"
,
LsaNtStatusToWinError
(
ntStatus
));
LsaClose
(
policyHandle
);
return
ntStatus
;
}
domainIdentifier
=
domainInfo
->
DomainSid
;
domainNameLen
=
lstrlenW
(
domainInfo
->
DomainName
.
Buffer
)
+
1
;
LsaClose
(
policyHandle
);
ntStatus
=
NetApiBufferAllocate
(
sizeof
(
USER_MODALS_INFO_2
)
+
GetLengthSid
(
domainIdentifier
)
+
domainNameLen
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
pbuffer
);
if
(
ntStatus
!=
NERR_Success
)
{
WARN
(
"NetApiBufferAllocate() failed
\n
"
);
LsaFreeMemory
(
domainInfo
);
return
ntStatus
;
}
umi
=
(
USER_MODALS_INFO_2
*
)
*
pbuffer
;
umi
->
usrmod2_domain_id
=
*
pbuffer
+
sizeof
(
USER_MODALS_INFO_2
);
umi
->
usrmod2_domain_name
=
(
LPWSTR
)(
*
pbuffer
+
sizeof
(
USER_MODALS_INFO_2
)
+
GetLengthSid
(
domainIdentifier
));
lstrcpynW
(
umi
->
usrmod2_domain_name
,
domainInfo
->
DomainName
.
Buffer
,
domainNameLen
);
CopySid
(
GetLengthSid
(
domainIdentifier
),
umi
->
usrmod2_domain_id
,
domainIdentifier
);
LsaFreeMemory
(
domainInfo
);
break
;
}
case
3
:
/* return lockout information */
FIXME
(
"level 3 not implemented!
\n
"
);
*
pbuffer
=
NULL
;
return
NERR_InternalError
;
default:
TRACE
(
"Invalid level %d is specified
\n
"
,
level
);
*
pbuffer
=
NULL
;
return
ERROR_INVALID_LEVEL
;
}
return
NERR_Success
;
}
static
char
*
strdup_unixcp
(
const
WCHAR
*
str
)
{
char
*
ret
;
int
len
=
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
str
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
((
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
)))
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
str
,
-
1
,
ret
,
len
,
NULL
,
NULL
);
return
ret
;
}
static
NET_API_STATUS
change_password_smb
(
LPCWSTR
domainname
,
LPCWSTR
username
,
LPCWSTR
oldpassword
,
LPCWSTR
newpassword
)
{
#ifdef HAVE_FORK
NET_API_STATUS
ret
=
NERR_Success
;
static
char
option_silent
[]
=
"-s"
;
static
char
option_user
[]
=
"-U"
;
static
char
option_remote
[]
=
"-r"
;
static
char
smbpasswd
[]
=
"smbpasswd"
;
int
pipe_out
[
2
];
pid_t
pid
,
wret
;
int
status
;
char
*
server
=
NULL
,
*
user
,
*
argv
[
7
],
*
old
=
NULL
,
*
new
=
NULL
;
if
(
domainname
&&
!
(
server
=
strdup_unixcp
(
domainname
)))
return
ERROR_OUTOFMEMORY
;
if
(
!
(
user
=
strdup_unixcp
(
username
)))
{
ret
=
ERROR_OUTOFMEMORY
;
goto
end
;
}
if
(
!
(
old
=
strdup_unixcp
(
oldpassword
)))
{
ret
=
ERROR_OUTOFMEMORY
;
goto
end
;
}
if
(
!
(
new
=
strdup_unixcp
(
newpassword
)))
{
ret
=
ERROR_OUTOFMEMORY
;
goto
end
;
}
argv
[
0
]
=
smbpasswd
;
argv
[
1
]
=
option_silent
;
argv
[
2
]
=
option_user
;
argv
[
3
]
=
user
;
if
(
server
)
{
argv
[
4
]
=
option_remote
;
argv
[
5
]
=
server
;
argv
[
6
]
=
NULL
;
}
else
argv
[
4
]
=
NULL
;
if
(
pipe
(
pipe_out
)
==
-
1
)
{
ret
=
NERR_InternalError
;
goto
end
;
}
fcntl
(
pipe_out
[
0
],
F_SETFD
,
FD_CLOEXEC
);
fcntl
(
pipe_out
[
1
],
F_SETFD
,
FD_CLOEXEC
);
switch
((
pid
=
fork
()))
{
case
-
1
:
close
(
pipe_out
[
0
]
);
close
(
pipe_out
[
1
]
);
ret
=
NERR_InternalError
;
goto
end
;
case
0
:
dup2
(
pipe_out
[
0
],
0
);
close
(
pipe_out
[
0
]
);
close
(
pipe_out
[
1
]
);
execvp
(
"smbpasswd"
,
argv
);
ERR
(
"can't execute smbpasswd, is it installed?
\n
"
);
_exit
(
1
);
default:
close
(
pipe_out
[
0
]
);
break
;
}
write
(
pipe_out
[
1
],
old
,
strlen
(
old
)
);
write
(
pipe_out
[
1
],
"
\n
"
,
1
);
write
(
pipe_out
[
1
],
new
,
strlen
(
new
)
);
write
(
pipe_out
[
1
],
"
\n
"
,
1
);
write
(
pipe_out
[
1
],
new
,
strlen
(
new
)
);
write
(
pipe_out
[
1
],
"
\n
"
,
1
);
close
(
pipe_out
[
1
]
);
do
{
wret
=
waitpid
(
pid
,
&
status
,
0
);
}
while
(
wret
<
0
&&
errno
==
EINTR
);
if
(
ret
==
NERR_Success
&&
(
wret
<
0
||
!
WIFEXITED
(
status
)
||
WEXITSTATUS
(
status
)))
ret
=
NERR_InternalError
;
end:
HeapFree
(
GetProcessHeap
(),
0
,
server
);
HeapFree
(
GetProcessHeap
(),
0
,
user
);
HeapFree
(
GetProcessHeap
(),
0
,
old
);
HeapFree
(
GetProcessHeap
(),
0
,
new
);
return
ret
;
#else
ERR
(
"no fork support on this platform
\n
"
);
return
NERR_InternalError
;
#endif
}
/******************************************************************************
* NetUserChangePassword (NETAPI32.@)
* PARAMS
* domainname [I] Optional. Domain on which the user resides or the logon
* domain of the current user if NULL.
* username [I] Optional. Username to change the password for or the name
* of the current user if NULL.
* oldpassword [I] The user's current password.
* newpassword [I] The password that the user will be changed to using.
*
* RETURNS
* Success: NERR_Success.
* Failure: NERR_* failure code or win error code.
*
*/
NET_API_STATUS
WINAPI
NetUserChangePassword
(
LPCWSTR
domainname
,
LPCWSTR
username
,
LPCWSTR
oldpassword
,
LPCWSTR
newpassword
)
{
struct
sam_user
*
user
;
TRACE
(
"(%s, %s, ..., ...)
\n
"
,
debugstr_w
(
domainname
),
debugstr_w
(
username
));
if
(
!
change_password_smb
(
domainname
,
username
,
oldpassword
,
newpassword
))
return
NERR_Success
;
if
(
domainname
)
FIXME
(
"Ignoring domainname %s.
\n
"
,
debugstr_w
(
domainname
));
if
((
user
=
NETAPI_FindUser
(
username
))
==
NULL
)
return
NERR_UserNotFound
;
if
(
lstrcmpW
(
user
->
user_password
,
oldpassword
)
!=
0
)
return
ERROR_INVALID_PASSWORD
;
if
(
lstrlenW
(
newpassword
)
>
PWLEN
)
return
ERROR_PASSWORD_RESTRICTION
;
lstrcpyW
(
user
->
user_password
,
newpassword
);
return
NERR_Success
;
}
NET_API_STATUS
WINAPI
NetUseAdd
(
LMSTR
servername
,
DWORD
level
,
LPBYTE
bufptr
,
LPDWORD
parm_err
)
{
FIXME
(
"%s %d %p %p stub
\n
"
,
debugstr_w
(
servername
),
level
,
bufptr
,
parm_err
);
return
NERR_Success
;
}
NET_API_STATUS
WINAPI
NetUseDel
(
LMSTR
servername
,
LMSTR
usename
,
DWORD
forcecond
)
{
FIXME
(
"%s %s %d stub
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
usename
),
forcecond
);
return
NERR_Success
;
}
dlls/netapi32/netapi32.c
View file @
97bc30ae
...
...
@@ -20,11 +20,21 @@
#include "config.h"
#include <stdarg.h>
#include <fcntl.h>
#include <errno.h>
#ifdef HAVE_SYS_WAIT_H
#include <sys/wait.h>
#endif
#ifdef HAVE_UNISTD_H
#include <unistd.h>
#endif
#include "ntstatus.h"
#define WIN32_NO_STATUS
#include "windef.h"
#include "winbase.h"
#include "lm.h"
#include "lmaccess.h"
#include "lmat.h"
#include "lmapibuf.h"
#include "lmshare.h"
...
...
@@ -33,7 +43,9 @@
#include "ifmib.h"
#include "iphlpapi.h"
#include "ntsecapi.h"
#include "winnls.h"
#include "wine/debug.h"
#include "wine/list.h"
WINE_DEFAULT_DEBUG_CHANNEL
(
netapi32
);
...
...
@@ -973,3 +985,993 @@ NET_API_STATUS NET_API_FUNCTION NetUserGetGroups(
return
ERROR_INVALID_LEVEL
;
}
struct
sam_user
{
struct
list
entry
;
WCHAR
user_name
[
LM20_UNLEN
+
1
];
WCHAR
user_password
[
PWLEN
+
1
];
DWORD
sec_since_passwd_change
;
DWORD
user_priv
;
LPWSTR
home_dir
;
LPWSTR
user_comment
;
DWORD
user_flags
;
LPWSTR
user_logon_script_path
;
};
static
struct
list
user_list
=
LIST_INIT
(
user_list
);
/************************************************************
* NETAPI_ValidateServername
*
* Validates server name
*/
static
NET_API_STATUS
NETAPI_ValidateServername
(
LPCWSTR
ServerName
)
{
if
(
ServerName
)
{
if
(
ServerName
[
0
]
==
0
)
return
ERROR_BAD_NETPATH
;
else
if
(
((
ServerName
[
0
]
==
'\\'
)
&&
(
ServerName
[
1
]
!=
'\\'
))
||
((
ServerName
[
0
]
==
'\\'
)
&&
(
ServerName
[
1
]
==
'\\'
)
&&
(
ServerName
[
2
]
==
0
))
)
return
ERROR_INVALID_NAME
;
}
return
NERR_Success
;
}
/************************************************************
* NETAPI_FindUser
*
* Looks for a user in the user database.
* Returns a pointer to the entry in the user list when the user
* is found, NULL otherwise.
*/
static
struct
sam_user
*
NETAPI_FindUser
(
LPCWSTR
UserName
)
{
struct
sam_user
*
user
;
LIST_FOR_EACH_ENTRY
(
user
,
&
user_list
,
struct
sam_user
,
entry
)
{
if
(
lstrcmpW
(
user
->
user_name
,
UserName
)
==
0
)
return
user
;
}
return
NULL
;
}
static
BOOL
NETAPI_IsCurrentUser
(
LPCWSTR
username
)
{
LPWSTR
curr_user
=
NULL
;
DWORD
dwSize
;
BOOL
ret
=
FALSE
;
dwSize
=
LM20_UNLEN
+
1
;
curr_user
=
HeapAlloc
(
GetProcessHeap
(),
0
,
dwSize
*
sizeof
(
WCHAR
));
if
(
!
curr_user
)
{
ERR
(
"Failed to allocate memory for user name.
\n
"
);
goto
end
;
}
if
(
!
GetUserNameW
(
curr_user
,
&
dwSize
))
{
ERR
(
"Failed to get current user's user name.
\n
"
);
goto
end
;
}
if
(
!
lstrcmpW
(
curr_user
,
username
))
{
ret
=
TRUE
;
}
end:
HeapFree
(
GetProcessHeap
(),
0
,
curr_user
);
return
ret
;
}
/************************************************************
* NetUserAdd (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserAdd
(
LPCWSTR
servername
,
DWORD
level
,
LPBYTE
bufptr
,
LPDWORD
parm_err
)
{
NET_API_STATUS
status
;
struct
sam_user
*
su
=
NULL
;
FIXME
(
"(%s, %d, %p, %p) stub!
\n
"
,
debugstr_w
(
servername
),
level
,
bufptr
,
parm_err
);
if
((
status
=
NETAPI_ValidateServername
(
servername
))
!=
NERR_Success
)
return
status
;
switch
(
level
)
{
/* Level 3 and 4 are identical for the purposes of NetUserAdd */
case
4
:
case
3
:
FIXME
(
"Level 3 and 4 not implemented.
\n
"
);
/* Fall through */
case
2
:
FIXME
(
"Level 2 not implemented.
\n
"
);
/* Fall through */
case
1
:
{
PUSER_INFO_1
ui
=
(
PUSER_INFO_1
)
bufptr
;
su
=
HeapAlloc
(
GetProcessHeap
(),
0
,
sizeof
(
struct
sam_user
));
if
(
!
su
)
{
status
=
NERR_InternalError
;
break
;
}
if
(
lstrlenW
(
ui
->
usri1_name
)
>
LM20_UNLEN
)
{
status
=
NERR_BadUsername
;
break
;
}
/*FIXME: do other checks for a valid username */
lstrcpyW
(
su
->
user_name
,
ui
->
usri1_name
);
if
(
lstrlenW
(
ui
->
usri1_password
)
>
PWLEN
)
{
/* Always return PasswordTooShort on invalid passwords. */
status
=
NERR_PasswordTooShort
;
break
;
}
lstrcpyW
(
su
->
user_password
,
ui
->
usri1_password
);
su
->
sec_since_passwd_change
=
ui
->
usri1_password_age
;
su
->
user_priv
=
ui
->
usri1_priv
;
su
->
user_flags
=
ui
->
usri1_flags
;
/*FIXME: set the other LPWSTRs to NULL for now */
su
->
home_dir
=
NULL
;
su
->
user_comment
=
NULL
;
su
->
user_logon_script_path
=
NULL
;
list_add_head
(
&
user_list
,
&
su
->
entry
);
return
NERR_Success
;
}
default:
TRACE
(
"Invalid level %d specified.
\n
"
,
level
);
status
=
ERROR_INVALID_LEVEL
;
break
;
}
HeapFree
(
GetProcessHeap
(),
0
,
su
);
return
status
;
}
/************************************************************
* NetUserDel (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserDel
(
LPCWSTR
servername
,
LPCWSTR
username
)
{
NET_API_STATUS
status
;
struct
sam_user
*
user
;
TRACE
(
"(%s, %s)
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
username
));
if
((
status
=
NETAPI_ValidateServername
(
servername
))
!=
NERR_Success
)
return
status
;
if
((
user
=
NETAPI_FindUser
(
username
))
==
NULL
)
return
NERR_UserNotFound
;
list_remove
(
&
user
->
entry
);
HeapFree
(
GetProcessHeap
(),
0
,
user
->
home_dir
);
HeapFree
(
GetProcessHeap
(),
0
,
user
->
user_comment
);
HeapFree
(
GetProcessHeap
(),
0
,
user
->
user_logon_script_path
);
HeapFree
(
GetProcessHeap
(),
0
,
user
);
return
NERR_Success
;
}
/************************************************************
* NetUserGetInfo (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserGetInfo
(
LPCWSTR
servername
,
LPCWSTR
username
,
DWORD
level
,
LPBYTE
*
bufptr
)
{
NET_API_STATUS
status
;
TRACE
(
"(%s, %s, %d, %p)
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
username
),
level
,
bufptr
);
status
=
NETAPI_ValidateServername
(
servername
);
if
(
status
!=
NERR_Success
)
return
status
;
if
(
!
NETAPI_IsLocalComputer
(
servername
))
{
FIXME
(
"Only implemented for local computer, but remote server"
"%s was requested.
\n
"
,
debugstr_w
(
servername
));
return
NERR_InvalidComputer
;
}
if
(
!
NETAPI_FindUser
(
username
)
&&
!
NETAPI_IsCurrentUser
(
username
))
{
TRACE
(
"User %s is unknown.
\n
"
,
debugstr_w
(
username
));
return
NERR_UserNotFound
;
}
switch
(
level
)
{
case
0
:
{
PUSER_INFO_0
ui
;
int
name_sz
;
name_sz
=
lstrlenW
(
username
)
+
1
;
/* set up buffer */
NetApiBufferAllocate
(
sizeof
(
USER_INFO_0
)
+
name_sz
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
bufptr
);
ui
=
(
PUSER_INFO_0
)
*
bufptr
;
ui
->
usri0_name
=
(
LPWSTR
)
(
*
bufptr
+
sizeof
(
USER_INFO_0
));
/* get data */
lstrcpyW
(
ui
->
usri0_name
,
username
);
break
;
}
case
10
:
{
PUSER_INFO_10
ui
;
PUSER_INFO_0
ui0
;
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
usr_comment_sz
,
full_name_sz
;
comment_sz
=
1
;
usr_comment_sz
=
1
;
full_name_sz
=
1
;
/* get data */
status
=
NetUserGetInfo
(
servername
,
username
,
0
,
(
LPBYTE
*
)
&
ui0
);
if
(
status
!=
NERR_Success
)
{
NetApiBufferFree
(
ui0
);
return
status
;
}
name_sz
=
lstrlenW
(
ui0
->
usri0_name
)
+
1
;
/* set up buffer */
NetApiBufferAllocate
(
sizeof
(
USER_INFO_10
)
+
(
name_sz
+
comment_sz
+
usr_comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
bufptr
);
ui
=
(
PUSER_INFO_10
)
*
bufptr
;
ui
->
usri10_name
=
(
LPWSTR
)
(
*
bufptr
+
sizeof
(
USER_INFO_10
));
ui
->
usri10_comment
=
(
LPWSTR
)
(
((
PBYTE
)
ui
->
usri10_name
)
+
name_sz
*
sizeof
(
WCHAR
));
ui
->
usri10_usr_comment
=
(
LPWSTR
)
(
((
PBYTE
)
ui
->
usri10_comment
)
+
comment_sz
*
sizeof
(
WCHAR
));
ui
->
usri10_full_name
=
(
LPWSTR
)
(
((
PBYTE
)
ui
->
usri10_usr_comment
)
+
usr_comment_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
ui
->
usri10_name
,
ui0
->
usri0_name
);
NetApiBufferFree
(
ui0
);
ui
->
usri10_comment
[
0
]
=
0
;
ui
->
usri10_usr_comment
[
0
]
=
0
;
ui
->
usri10_full_name
[
0
]
=
0
;
break
;
}
case
1
:
{
static
const
WCHAR
homedirW
[]
=
{
'H'
,
'O'
,
'M'
,
'E'
,
0
};
PUSER_INFO_1
ui
;
PUSER_INFO_0
ui0
;
/* sizes of the field buffers in WCHARS */
int
name_sz
,
password_sz
,
home_dir_sz
,
comment_sz
,
script_path_sz
;
password_sz
=
1
;
/* not filled out for security reasons for NetUserGetInfo*/
comment_sz
=
1
;
script_path_sz
=
1
;
/* get data */
status
=
NetUserGetInfo
(
servername
,
username
,
0
,
(
LPBYTE
*
)
&
ui0
);
if
(
status
!=
NERR_Success
)
{
NetApiBufferFree
(
ui0
);
return
status
;
}
name_sz
=
lstrlenW
(
ui0
->
usri0_name
)
+
1
;
home_dir_sz
=
GetEnvironmentVariableW
(
homedirW
,
NULL
,
0
);
/* set up buffer */
NetApiBufferAllocate
(
sizeof
(
USER_INFO_1
)
+
(
name_sz
+
password_sz
+
home_dir_sz
+
comment_sz
+
script_path_sz
)
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
bufptr
);
ui
=
(
PUSER_INFO_1
)
*
bufptr
;
ui
->
usri1_name
=
(
LPWSTR
)
(
ui
+
1
);
ui
->
usri1_password
=
ui
->
usri1_name
+
name_sz
;
ui
->
usri1_home_dir
=
ui
->
usri1_password
+
password_sz
;
ui
->
usri1_comment
=
ui
->
usri1_home_dir
+
home_dir_sz
;
ui
->
usri1_script_path
=
ui
->
usri1_comment
+
comment_sz
;
/* set data */
lstrcpyW
(
ui
->
usri1_name
,
ui0
->
usri0_name
);
NetApiBufferFree
(
ui0
);
ui
->
usri1_password
[
0
]
=
0
;
ui
->
usri1_password_age
=
0
;
ui
->
usri1_priv
=
0
;
GetEnvironmentVariableW
(
homedirW
,
ui
->
usri1_home_dir
,
home_dir_sz
);
ui
->
usri1_comment
[
0
]
=
0
;
ui
->
usri1_flags
=
0
;
ui
->
usri1_script_path
[
0
]
=
0
;
break
;
}
case
2
:
case
3
:
case
4
:
case
11
:
case
20
:
case
23
:
case
1003
:
case
1005
:
case
1006
:
case
1007
:
case
1008
:
case
1009
:
case
1010
:
case
1011
:
case
1012
:
case
1013
:
case
1014
:
case
1017
:
case
1018
:
case
1020
:
case
1023
:
case
1024
:
case
1025
:
case
1051
:
case
1052
:
case
1053
:
{
FIXME
(
"Level %d is not implemented
\n
"
,
level
);
return
NERR_InternalError
;
}
default:
TRACE
(
"Invalid level %d is specified
\n
"
,
level
);
return
ERROR_INVALID_LEVEL
;
}
return
NERR_Success
;
}
/************************************************************
* NetUserGetLocalGroups (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserGetLocalGroups
(
LPCWSTR
servername
,
LPCWSTR
username
,
DWORD
level
,
DWORD
flags
,
LPBYTE
*
bufptr
,
DWORD
prefmaxlen
,
LPDWORD
entriesread
,
LPDWORD
totalentries
)
{
NET_API_STATUS
status
;
const
WCHAR
admins
[]
=
{
'A'
,
'd'
,
'm'
,
'i'
,
'n'
,
'i'
,
's'
,
't'
,
'r'
,
'a'
,
't'
,
'o'
,
'r'
,
's'
,
0
};
LPWSTR
currentuser
;
LOCALGROUP_USERS_INFO_0
*
info
;
DWORD
size
;
FIXME
(
"(%s, %s, %d, %08x, %p %d, %p, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
username
),
level
,
flags
,
bufptr
,
prefmaxlen
,
entriesread
,
totalentries
);
status
=
NETAPI_ValidateServername
(
servername
);
if
(
status
!=
NERR_Success
)
return
status
;
size
=
UNLEN
+
1
;
NetApiBufferAllocate
(
size
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
&
currentuser
);
if
(
!
GetUserNameW
(
currentuser
,
&
size
))
{
NetApiBufferFree
(
currentuser
);
return
ERROR_NOT_ENOUGH_MEMORY
;
}
if
(
lstrcmpiW
(
username
,
currentuser
)
&&
NETAPI_FindUser
(
username
))
{
NetApiBufferFree
(
currentuser
);
return
NERR_UserNotFound
;
}
NetApiBufferFree
(
currentuser
);
*
totalentries
=
1
;
size
=
sizeof
(
*
info
)
+
sizeof
(
admins
);
if
(
prefmaxlen
<
size
)
status
=
ERROR_MORE_DATA
;
else
status
=
NetApiBufferAllocate
(
size
,
(
LPVOID
*
)
&
info
);
if
(
status
!=
NERR_Success
)
{
*
bufptr
=
NULL
;
*
entriesread
=
0
;
return
status
;
}
info
->
lgrui0_name
=
(
LPWSTR
)((
LPBYTE
)
info
+
sizeof
(
*
info
));
lstrcpyW
(
info
->
lgrui0_name
,
admins
);
*
bufptr
=
(
LPBYTE
)
info
;
*
entriesread
=
1
;
return
NERR_Success
;
}
/************************************************************
* NetUserEnum (NETAPI32.@)
*/
NET_API_STATUS
WINAPI
NetUserEnum
(
LPCWSTR
servername
,
DWORD
level
,
DWORD
filter
,
LPBYTE
*
bufptr
,
DWORD
prefmaxlen
,
LPDWORD
entriesread
,
LPDWORD
totalentries
,
LPDWORD
resume_handle
)
{
FIXME
(
"(%s,%d, 0x%d,%p,%d,%p,%p,%p) stub!
\n
"
,
debugstr_w
(
servername
),
level
,
filter
,
bufptr
,
prefmaxlen
,
entriesread
,
totalentries
,
resume_handle
);
return
ERROR_ACCESS_DENIED
;
}
/************************************************************
* ACCESS_QueryAdminDisplayInformation
*
* Creates a buffer with information for the Admin User
*/
static
void
ACCESS_QueryAdminDisplayInformation
(
PNET_DISPLAY_USER
*
buf
,
PDWORD
pdwSize
)
{
static
const
WCHAR
sAdminUserName
[]
=
{
'A'
,
'd'
,
'm'
,
'i'
,
'n'
,
'i'
,
's'
,
't'
,
'r'
,
'a'
,
't'
,
'o'
,
'r'
,
0
};
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
full_name_sz
;
PNET_DISPLAY_USER
usr
;
/* set up buffer */
name_sz
=
lstrlenW
(
sAdminUserName
)
+
1
;
comment_sz
=
1
;
full_name_sz
=
1
;
*
pdwSize
=
sizeof
(
NET_DISPLAY_USER
);
*
pdwSize
+=
(
name_sz
+
comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
);
NetApiBufferAllocate
(
*
pdwSize
,
(
LPVOID
*
)
buf
);
usr
=
*
buf
;
usr
->
usri1_name
=
(
LPWSTR
)
((
PBYTE
)
usr
+
sizeof
(
NET_DISPLAY_USER
));
usr
->
usri1_comment
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_name
)
+
name_sz
*
sizeof
(
WCHAR
));
usr
->
usri1_full_name
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_comment
)
+
comment_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
usr
->
usri1_name
,
sAdminUserName
);
usr
->
usri1_comment
[
0
]
=
0
;
usr
->
usri1_flags
=
UF_SCRIPT
|
UF_NORMAL_ACCOUNT
|
UF_DONT_EXPIRE_PASSWD
;
usr
->
usri1_full_name
[
0
]
=
0
;
usr
->
usri1_user_id
=
DOMAIN_USER_RID_ADMIN
;
usr
->
usri1_next_index
=
0
;
}
/************************************************************
* ACCESS_QueryGuestDisplayInformation
*
* Creates a buffer with information for the Guest User
*/
static
void
ACCESS_QueryGuestDisplayInformation
(
PNET_DISPLAY_USER
*
buf
,
PDWORD
pdwSize
)
{
static
const
WCHAR
sGuestUserName
[]
=
{
'G'
,
'u'
,
'e'
,
's'
,
't'
,
0
};
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
full_name_sz
;
PNET_DISPLAY_USER
usr
;
/* set up buffer */
name_sz
=
lstrlenW
(
sGuestUserName
)
+
1
;
comment_sz
=
1
;
full_name_sz
=
1
;
*
pdwSize
=
sizeof
(
NET_DISPLAY_USER
);
*
pdwSize
+=
(
name_sz
+
comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
);
NetApiBufferAllocate
(
*
pdwSize
,
(
LPVOID
*
)
buf
);
usr
=
*
buf
;
usr
->
usri1_name
=
(
LPWSTR
)
((
PBYTE
)
usr
+
sizeof
(
NET_DISPLAY_USER
));
usr
->
usri1_comment
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_name
)
+
name_sz
*
sizeof
(
WCHAR
));
usr
->
usri1_full_name
=
(
LPWSTR
)
(
((
PBYTE
)
usr
->
usri1_comment
)
+
comment_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
usr
->
usri1_name
,
sGuestUserName
);
usr
->
usri1_comment
[
0
]
=
0
;
usr
->
usri1_flags
=
UF_ACCOUNTDISABLE
|
UF_SCRIPT
|
UF_NORMAL_ACCOUNT
|
UF_DONT_EXPIRE_PASSWD
;
usr
->
usri1_full_name
[
0
]
=
0
;
usr
->
usri1_user_id
=
DOMAIN_USER_RID_GUEST
;
usr
->
usri1_next_index
=
0
;
}
/************************************************************
* Copies NET_DISPLAY_USER record.
*/
static
void
ACCESS_CopyDisplayUser
(
const
NET_DISPLAY_USER
*
dest
,
LPWSTR
*
dest_buf
,
PNET_DISPLAY_USER
src
)
{
LPWSTR
str
=
*
dest_buf
;
src
->
usri1_name
=
str
;
lstrcpyW
(
src
->
usri1_name
,
dest
->
usri1_name
);
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
));
src
->
usri1_comment
=
str
;
lstrcpyW
(
src
->
usri1_comment
,
dest
->
usri1_comment
);
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
));
src
->
usri1_flags
=
dest
->
usri1_flags
;
src
->
usri1_full_name
=
str
;
lstrcpyW
(
src
->
usri1_full_name
,
dest
->
usri1_full_name
);
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
(
lstrlenW
(
str
)
+
1
)
*
sizeof
(
WCHAR
));
src
->
usri1_user_id
=
dest
->
usri1_user_id
;
src
->
usri1_next_index
=
dest
->
usri1_next_index
;
*
dest_buf
=
str
;
}
/************************************************************
* NetQueryDisplayInformation (NETAPI32.@)
*
* The buffer structure:
* - array of fixed size record of the level type
* - strings, referenced by the record of the level type
*/
NET_API_STATUS
WINAPI
NetQueryDisplayInformation
(
LPCWSTR
ServerName
,
DWORD
Level
,
DWORD
Index
,
DWORD
EntriesRequested
,
DWORD
PreferredMaximumLength
,
LPDWORD
ReturnedEntryCount
,
PVOID
*
SortedBuffer
)
{
TRACE
(
"(%s, %d, %d, %d, %d, %p, %p)
\n
"
,
debugstr_w
(
ServerName
),
Level
,
Index
,
EntriesRequested
,
PreferredMaximumLength
,
ReturnedEntryCount
,
SortedBuffer
);
if
(
!
NETAPI_IsLocalComputer
(
ServerName
))
{
FIXME
(
"Only implemented on local computer, but requested for "
"remote server %s
\n
"
,
debugstr_w
(
ServerName
));
return
ERROR_ACCESS_DENIED
;
}
switch
(
Level
)
{
case
1
:
{
/* current record */
PNET_DISPLAY_USER
inf
;
/* current available strings buffer */
LPWSTR
str
;
PNET_DISPLAY_USER
admin
,
guest
;
DWORD
admin_size
,
guest_size
;
LPWSTR
name
=
NULL
;
DWORD
dwSize
;
/* sizes of the field buffers in WCHARS */
int
name_sz
,
comment_sz
,
full_name_sz
;
/* number of the records, returned in SortedBuffer
3 - for current user, Administrator and Guest users
*/
int
records
=
3
;
FIXME
(
"Level %d partially implemented
\n
"
,
Level
);
*
ReturnedEntryCount
=
records
;
comment_sz
=
1
;
full_name_sz
=
1
;
/* get data */
dwSize
=
UNLEN
+
1
;
NetApiBufferAllocate
(
dwSize
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
&
name
);
if
(
!
GetUserNameW
(
name
,
&
dwSize
))
{
NetApiBufferFree
(
name
);
return
ERROR_ACCESS_DENIED
;
}
name_sz
=
dwSize
;
ACCESS_QueryAdminDisplayInformation
(
&
admin
,
&
admin_size
);
ACCESS_QueryGuestDisplayInformation
(
&
guest
,
&
guest_size
);
/* set up buffer */
dwSize
=
sizeof
(
NET_DISPLAY_USER
)
*
records
;
dwSize
+=
(
name_sz
+
comment_sz
+
full_name_sz
)
*
sizeof
(
WCHAR
);
NetApiBufferAllocate
(
dwSize
+
admin_size
-
sizeof
(
NET_DISPLAY_USER
)
+
guest_size
-
sizeof
(
NET_DISPLAY_USER
),
SortedBuffer
);
inf
=
*
SortedBuffer
;
str
=
(
LPWSTR
)
((
PBYTE
)
inf
+
sizeof
(
NET_DISPLAY_USER
)
*
records
);
inf
->
usri1_name
=
str
;
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
name_sz
*
sizeof
(
WCHAR
));
inf
->
usri1_comment
=
str
;
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
comment_sz
*
sizeof
(
WCHAR
));
inf
->
usri1_full_name
=
str
;
str
=
(
LPWSTR
)
(
((
PBYTE
)
str
)
+
full_name_sz
*
sizeof
(
WCHAR
));
/* set data */
lstrcpyW
(
inf
->
usri1_name
,
name
);
NetApiBufferFree
(
name
);
inf
->
usri1_comment
[
0
]
=
0
;
inf
->
usri1_flags
=
UF_SCRIPT
|
UF_NORMAL_ACCOUNT
|
UF_DONT_EXPIRE_PASSWD
;
inf
->
usri1_full_name
[
0
]
=
0
;
inf
->
usri1_user_id
=
0
;
inf
->
usri1_next_index
=
0
;
inf
++
;
ACCESS_CopyDisplayUser
(
admin
,
&
str
,
inf
);
NetApiBufferFree
(
admin
);
inf
++
;
ACCESS_CopyDisplayUser
(
guest
,
&
str
,
inf
);
NetApiBufferFree
(
guest
);
break
;
}
case
2
:
case
3
:
{
FIXME
(
"Level %d is not implemented
\n
"
,
Level
);
break
;
}
default:
TRACE
(
"Invalid level %d is specified
\n
"
,
Level
);
return
ERROR_INVALID_LEVEL
;
}
return
NERR_Success
;
}
/************************************************************
* NetGetDCName (NETAPI32.@)
*
* Return the name of the primary domain controller (PDC)
*/
NET_API_STATUS
WINAPI
NetGetDCName
(
LPCWSTR
servername
,
LPCWSTR
domainname
,
LPBYTE
*
bufptr
)
{
FIXME
(
"(%s, %s, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
domainname
),
bufptr
);
return
NERR_DCNotFound
;
/* say we can't find a domain controller */
}
/************************************************************
* NetGetAnyDCName (NETAPI32.@)
*
* Return the name of any domain controller (DC) for a
* domain that is directly trusted by the specified server
*/
NET_API_STATUS
WINAPI
NetGetAnyDCName
(
LPCWSTR
servername
,
LPCWSTR
domainname
,
LPBYTE
*
bufptr
)
{
FIXME
(
"(%s, %s, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
domainname
),
bufptr
);
return
ERROR_NO_SUCH_DOMAIN
;
}
/************************************************************
* NetGroupEnum (NETAPI32.@)
*
*/
NET_API_STATUS
WINAPI
NetGroupEnum
(
LPCWSTR
servername
,
DWORD
level
,
LPBYTE
*
bufptr
,
DWORD
prefmaxlen
,
LPDWORD
entriesread
,
LPDWORD
totalentries
,
LPDWORD
resume_handle
)
{
FIXME
(
"(%s, %d, %p, %d, %p, %p, %p) stub!
\n
"
,
debugstr_w
(
servername
),
level
,
bufptr
,
prefmaxlen
,
entriesread
,
totalentries
,
resume_handle
);
return
ERROR_ACCESS_DENIED
;
}
/************************************************************
* NetGroupGetInfo (NETAPI32.@)
*
*/
NET_API_STATUS
WINAPI
NetGroupGetInfo
(
LPCWSTR
servername
,
LPCWSTR
groupname
,
DWORD
level
,
LPBYTE
*
bufptr
)
{
FIXME
(
"(%s, %s, %d, %p) stub!
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
groupname
),
level
,
bufptr
);
return
ERROR_ACCESS_DENIED
;
}
/******************************************************************************
* NetUserModalsGet (NETAPI32.@)
*
* Retrieves global information for all users and global groups in the security
* database.
*
* PARAMS
* szServer [I] Specifies the DNS or the NetBIOS name of the remote server
* on which the function is to execute.
* level [I] Information level of the data.
* 0 Return global passwords parameters. bufptr points to a
* USER_MODALS_INFO_0 struct.
* 1 Return logon server and domain controller information. bufptr
* points to a USER_MODALS_INFO_1 struct.
* 2 Return domain name and identifier. bufptr points to a
* USER_MODALS_INFO_2 struct.
* 3 Return lockout information. bufptr points to a USER_MODALS_INFO_3
* struct.
* pbuffer [I] Buffer that receives the data.
*
* RETURNS
* Success: NERR_Success.
* Failure:
* ERROR_ACCESS_DENIED - the user does not have access to the info.
* NERR_InvalidComputer - computer name is invalid.
*/
NET_API_STATUS
WINAPI
NetUserModalsGet
(
LPCWSTR
szServer
,
DWORD
level
,
LPBYTE
*
pbuffer
)
{
TRACE
(
"(%s %d %p)
\n
"
,
debugstr_w
(
szServer
),
level
,
pbuffer
);
switch
(
level
)
{
case
0
:
/* return global passwords parameters */
FIXME
(
"level 0 not implemented!
\n
"
);
*
pbuffer
=
NULL
;
return
NERR_InternalError
;
case
1
:
/* return logon server and domain controller info */
FIXME
(
"level 1 not implemented!
\n
"
);
*
pbuffer
=
NULL
;
return
NERR_InternalError
;
case
2
:
{
/* return domain name and identifier */
PUSER_MODALS_INFO_2
umi
;
LSA_HANDLE
policyHandle
;
LSA_OBJECT_ATTRIBUTES
objectAttributes
;
PPOLICY_ACCOUNT_DOMAIN_INFO
domainInfo
;
NTSTATUS
ntStatus
;
PSID
domainIdentifier
=
NULL
;
int
domainNameLen
;
ZeroMemory
(
&
objectAttributes
,
sizeof
(
objectAttributes
));
objectAttributes
.
Length
=
sizeof
(
objectAttributes
);
ntStatus
=
LsaOpenPolicy
(
NULL
,
&
objectAttributes
,
POLICY_VIEW_LOCAL_INFORMATION
,
&
policyHandle
);
if
(
ntStatus
!=
STATUS_SUCCESS
)
{
WARN
(
"LsaOpenPolicy failed with NT status %x
\n
"
,
LsaNtStatusToWinError
(
ntStatus
));
return
ntStatus
;
}
ntStatus
=
LsaQueryInformationPolicy
(
policyHandle
,
PolicyAccountDomainInformation
,
(
PVOID
*
)
&
domainInfo
);
if
(
ntStatus
!=
STATUS_SUCCESS
)
{
WARN
(
"LsaQueryInformationPolicy failed with NT status %x
\n
"
,
LsaNtStatusToWinError
(
ntStatus
));
LsaClose
(
policyHandle
);
return
ntStatus
;
}
domainIdentifier
=
domainInfo
->
DomainSid
;
domainNameLen
=
lstrlenW
(
domainInfo
->
DomainName
.
Buffer
)
+
1
;
LsaClose
(
policyHandle
);
ntStatus
=
NetApiBufferAllocate
(
sizeof
(
USER_MODALS_INFO_2
)
+
GetLengthSid
(
domainIdentifier
)
+
domainNameLen
*
sizeof
(
WCHAR
),
(
LPVOID
*
)
pbuffer
);
if
(
ntStatus
!=
NERR_Success
)
{
WARN
(
"NetApiBufferAllocate() failed
\n
"
);
LsaFreeMemory
(
domainInfo
);
return
ntStatus
;
}
umi
=
(
USER_MODALS_INFO_2
*
)
*
pbuffer
;
umi
->
usrmod2_domain_id
=
*
pbuffer
+
sizeof
(
USER_MODALS_INFO_2
);
umi
->
usrmod2_domain_name
=
(
LPWSTR
)(
*
pbuffer
+
sizeof
(
USER_MODALS_INFO_2
)
+
GetLengthSid
(
domainIdentifier
));
lstrcpynW
(
umi
->
usrmod2_domain_name
,
domainInfo
->
DomainName
.
Buffer
,
domainNameLen
);
CopySid
(
GetLengthSid
(
domainIdentifier
),
umi
->
usrmod2_domain_id
,
domainIdentifier
);
LsaFreeMemory
(
domainInfo
);
break
;
}
case
3
:
/* return lockout information */
FIXME
(
"level 3 not implemented!
\n
"
);
*
pbuffer
=
NULL
;
return
NERR_InternalError
;
default:
TRACE
(
"Invalid level %d is specified
\n
"
,
level
);
*
pbuffer
=
NULL
;
return
ERROR_INVALID_LEVEL
;
}
return
NERR_Success
;
}
static
char
*
strdup_unixcp
(
const
WCHAR
*
str
)
{
char
*
ret
;
int
len
=
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
str
,
-
1
,
NULL
,
0
,
NULL
,
NULL
);
if
((
ret
=
HeapAlloc
(
GetProcessHeap
(),
0
,
len
)))
WideCharToMultiByte
(
CP_UNIXCP
,
0
,
str
,
-
1
,
ret
,
len
,
NULL
,
NULL
);
return
ret
;
}
static
NET_API_STATUS
change_password_smb
(
LPCWSTR
domainname
,
LPCWSTR
username
,
LPCWSTR
oldpassword
,
LPCWSTR
newpassword
)
{
#ifdef HAVE_FORK
NET_API_STATUS
ret
=
NERR_Success
;
static
char
option_silent
[]
=
"-s"
;
static
char
option_user
[]
=
"-U"
;
static
char
option_remote
[]
=
"-r"
;
static
char
smbpasswd
[]
=
"smbpasswd"
;
int
pipe_out
[
2
];
pid_t
pid
,
wret
;
int
status
;
char
*
server
=
NULL
,
*
user
,
*
argv
[
7
],
*
old
=
NULL
,
*
new
=
NULL
;
if
(
domainname
&&
!
(
server
=
strdup_unixcp
(
domainname
)))
return
ERROR_OUTOFMEMORY
;
if
(
!
(
user
=
strdup_unixcp
(
username
)))
{
ret
=
ERROR_OUTOFMEMORY
;
goto
end
;
}
if
(
!
(
old
=
strdup_unixcp
(
oldpassword
)))
{
ret
=
ERROR_OUTOFMEMORY
;
goto
end
;
}
if
(
!
(
new
=
strdup_unixcp
(
newpassword
)))
{
ret
=
ERROR_OUTOFMEMORY
;
goto
end
;
}
argv
[
0
]
=
smbpasswd
;
argv
[
1
]
=
option_silent
;
argv
[
2
]
=
option_user
;
argv
[
3
]
=
user
;
if
(
server
)
{
argv
[
4
]
=
option_remote
;
argv
[
5
]
=
server
;
argv
[
6
]
=
NULL
;
}
else
argv
[
4
]
=
NULL
;
if
(
pipe
(
pipe_out
)
==
-
1
)
{
ret
=
NERR_InternalError
;
goto
end
;
}
fcntl
(
pipe_out
[
0
],
F_SETFD
,
FD_CLOEXEC
);
fcntl
(
pipe_out
[
1
],
F_SETFD
,
FD_CLOEXEC
);
switch
((
pid
=
fork
()))
{
case
-
1
:
close
(
pipe_out
[
0
]
);
close
(
pipe_out
[
1
]
);
ret
=
NERR_InternalError
;
goto
end
;
case
0
:
dup2
(
pipe_out
[
0
],
0
);
close
(
pipe_out
[
0
]
);
close
(
pipe_out
[
1
]
);
execvp
(
"smbpasswd"
,
argv
);
ERR
(
"can't execute smbpasswd, is it installed?
\n
"
);
_exit
(
1
);
default:
close
(
pipe_out
[
0
]
);
break
;
}
write
(
pipe_out
[
1
],
old
,
strlen
(
old
)
);
write
(
pipe_out
[
1
],
"
\n
"
,
1
);
write
(
pipe_out
[
1
],
new
,
strlen
(
new
)
);
write
(
pipe_out
[
1
],
"
\n
"
,
1
);
write
(
pipe_out
[
1
],
new
,
strlen
(
new
)
);
write
(
pipe_out
[
1
],
"
\n
"
,
1
);
close
(
pipe_out
[
1
]
);
do
{
wret
=
waitpid
(
pid
,
&
status
,
0
);
}
while
(
wret
<
0
&&
errno
==
EINTR
);
if
(
ret
==
NERR_Success
&&
(
wret
<
0
||
!
WIFEXITED
(
status
)
||
WEXITSTATUS
(
status
)))
ret
=
NERR_InternalError
;
end:
HeapFree
(
GetProcessHeap
(),
0
,
server
);
HeapFree
(
GetProcessHeap
(),
0
,
user
);
HeapFree
(
GetProcessHeap
(),
0
,
old
);
HeapFree
(
GetProcessHeap
(),
0
,
new
);
return
ret
;
#else
ERR
(
"no fork support on this platform
\n
"
);
return
NERR_InternalError
;
#endif
}
/******************************************************************************
* NetUserChangePassword (NETAPI32.@)
* PARAMS
* domainname [I] Optional. Domain on which the user resides or the logon
* domain of the current user if NULL.
* username [I] Optional. Username to change the password for or the name
* of the current user if NULL.
* oldpassword [I] The user's current password.
* newpassword [I] The password that the user will be changed to using.
*
* RETURNS
* Success: NERR_Success.
* Failure: NERR_* failure code or win error code.
*
*/
NET_API_STATUS
WINAPI
NetUserChangePassword
(
LPCWSTR
domainname
,
LPCWSTR
username
,
LPCWSTR
oldpassword
,
LPCWSTR
newpassword
)
{
struct
sam_user
*
user
;
TRACE
(
"(%s, %s, ..., ...)
\n
"
,
debugstr_w
(
domainname
),
debugstr_w
(
username
));
if
(
!
change_password_smb
(
domainname
,
username
,
oldpassword
,
newpassword
))
return
NERR_Success
;
if
(
domainname
)
FIXME
(
"Ignoring domainname %s.
\n
"
,
debugstr_w
(
domainname
));
if
((
user
=
NETAPI_FindUser
(
username
))
==
NULL
)
return
NERR_UserNotFound
;
if
(
lstrcmpW
(
user
->
user_password
,
oldpassword
)
!=
0
)
return
ERROR_INVALID_PASSWORD
;
if
(
lstrlenW
(
newpassword
)
>
PWLEN
)
return
ERROR_PASSWORD_RESTRICTION
;
lstrcpyW
(
user
->
user_password
,
newpassword
);
return
NERR_Success
;
}
NET_API_STATUS
WINAPI
NetUseAdd
(
LMSTR
servername
,
DWORD
level
,
LPBYTE
bufptr
,
LPDWORD
parm_err
)
{
FIXME
(
"%s %d %p %p stub
\n
"
,
debugstr_w
(
servername
),
level
,
bufptr
,
parm_err
);
return
NERR_Success
;
}
NET_API_STATUS
WINAPI
NetUseDel
(
LMSTR
servername
,
LMSTR
usename
,
DWORD
forcecond
)
{
FIXME
(
"%s %s %d stub
\n
"
,
debugstr_w
(
servername
),
debugstr_w
(
usename
),
forcecond
);
return
NERR_Success
;
}
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