%% options
copyright owner = Dirk Krause
copyright year = 2015-xxxx
license = bsd
%% header
/** @file
Get information about user
(login name and home directory).
*/
#ifndef DK4CONF_H_INCLUDED
#include "dk4conf.h"
#endif
#ifndef DK4TYPES_H_INCLUDED
#include "dk4types.h"
#endif
#ifndef DK4ERROR_H_INCLUDED
#include "dk4error.h"
#endif
#ifdef __cplusplus
extern "C" {
#endif
/** Get users login name.
@param pdst Pointer to destination buffer.
@param szdst Size of destination buffer (number of characters).
@param eff Flag: Retrieve information about effective user.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
CRT on Windows: Not used.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if pdst is NULL or szdst is 0,
- DK4_E_NOT_FOUND
if the login name was not found,
- DK4_E_BUFFER_TOO_SMALL
if the buffer is too small for the result.
*/
int
dk4user_get_logname(dkChar *pdst, size_t szdst, int eff, dk4_er_t *erp);
/** Get users home directory.
@param pdst Pointer to destination buffer.
@param szdst Size of destination buffer (number of characters).
@param eff Flag: Retrieve information about effective user.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
CRT on Windows: Optional.
Error codes:
- DK4_E_INVALID_ARGUMENTS
if pdst is NULL or szdst is 0,
- DK4_E_NOT_FOUND
if the login name, the user entry or the home
directory was not found,
- DK4_E_MEMORY
if an internal memory allocation failed,
- DK4_E_SYNTAX
if the retrieved registry entry on
Windows is not a string,
- DK4_E_BUFFER_TOO_SMALL
if the pdst buffer or one of the internal buffers
is too small for the result.
*/
int
dk4user_get_homedir(dkChar *pdst, size_t szdst, int eff, dk4_er_t *erp);
#ifdef __cplusplus
}
#endif
%% module
#include "dk4user.h"
#include "dk4str8.h"
#include "dk4strw.h"
#include "dk4strd.h"
#include "dk4wregw.h"
#include "dk4wregc.h"
#include "dk4mem.h"
#include "dk4error.h"
#include "dk4masz.h"
#include "dk4mpl.h"
#if DK4_ON_WINDOWS
#ifndef WINDOWS_H_INCLUDED
#include
#define WINDOWS_H_INCLUDED 1
#endif
#ifndef LM_H_INCLUDED
#include
#define LM_H_INCLUDED 1
#endif
#ifndef SDDL_H_INCLUDED
#include
#define SDDL_H_INCLUDED 1
#endif
#endif
#if DK4_HAVE_SYS_TYPES_H
#ifndef SYS_TYPES_H_INCLUDED
#include
#define SYS_TYPES_H_INCLUDED 1
#endif
#endif
#if DK4_HAVE_UNISTD_H
#ifndef UNISTD_H_INCLUDED
#include
#define UNISTD_H_INCLUDED 1
#endif
#endif
#if DK4_HAVE_PWD_H
#ifndef PWD_H_INCLUDED
#include
#define PWD_H_INCLUDED 1
#endif
#endif
$!trace-include
#if DK4_ON_WINDOWS
static const wchar_t * const dk4user_kw[] = {
$!string-table prefix=L
#
# 0 ... 2 Registry key name and value name for profile dir
#
SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\ProfileList
\\
ProfileImagePath
#
# 3 4 5 6
#
LOGONSERVER
USERPROFILE
HOMEDRIVE
HOMEPATH
$!end
};
#endif
int
dk4user_get_logname(dkChar *pdst, size_t szdst, int eff, dk4_er_t *erp)
{
#if DK4_ON_WINDOWS
DWORD sz;
int back = 0;
$? "+ dk4user_get_logname (Windows)"
if ((NULL != pdst) && (0 < szdst)) {
sz = (DWORD)szdst;
#if DK4_CHAR_SIZE > 1
if(GetUserNameW(pdst, &sz))
#else
if(GetUserNameA(pdst, &sz))
#endif
{
if (sz < szdst) {
pdst[sz] = dkT('\0');
back = 1;
} else {
dk4error_set_simple_error_code(erp, DK4_E_BUFFER_TOO_SMALL);
}
}
else
{
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} $? "- dk4user_get_logname (Windows) %d", back
return back;
#else
#if DK4_CHAR_SIZE > 1
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return 0;
#else
struct passwd *pwent;
uid_t uid;
int back = 0;
$? "+ dk4user_get_logname (non-Windows, char)"
if ((NULL != pdst) && (0 < szdst)) {
if (0 != eff) { uid = geteuid(); } else { uid = getuid(); }
pwent = getpwuid(uid);
if (NULL != pwent) {
if (NULL != pwent->pw_name) {
if (0 != dk4str_cpy_s(pdst, szdst, pwent->pw_name, erp)) {
back = 1;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} $? "- dk4user_get_logname (non-Windows, char) %d", back
return back;
#endif
#endif
}
#if DK4_ON_WINDOWS
/** Obtain home directory information using one logon server.
@param pdst Destination buffer pointer.
@param szdst Destination buffer size (number of wchar_t).
@param lsn Logon server name, may be NULL.
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
*/
static
int
dk4user_get_i_ls_homedir(
wchar_t *pdst, size_t szdst, const wchar_t *lsn, dk4_er_t *erp
)
{
wchar_t b1[DK4_MAX_PATH+16]; /* Buffer RegQueryValue() */
wchar_t b2[DK4_MAX_PATH+16]; /* Buffer Expand...() */
wchar_t logname[256]; /* Login name */
dk4_er_t er; /* Error report */
USER_INFO_4 *pbuf4 = NULL; /* User information */
wchar_t *pStringSid = NULL; /* String SID */
wchar_t *keyname = NULL; /* Registry key name */
void *wrkey = NULL; /* Registry key */
DWORD szlog = DK4_SIZEOF(logname,wchar_t);
size_t sz = 0; /* Key name length */
int back = 0; /* Result */
NET_API_STATUS nStatus = 0; /* Network op result */
$? "+ dk4user_get_i_ls_homedir lsn=\"%!ws\"", TR_LSTR(lsn)
dk4error_init(&er);
if (GetUserNameW(logname, &szlog)) { $? ". user name found"
if (DK4_SIZEOF(logname,wchar_t) >= szlog) { $? ". name size ok"
logname[szlog] = L'\0';
nStatus = NetUserGetInfo(lsn, logname, (DWORD)4, (LPBYTE *)(&pbuf4));
if ((NERR_Success == nStatus) && (NULL != pbuf4)) { $? ". user info"
if (ConvertSidToStringSidW(pbuf4->usri4_user_sid, &pStringSid)) {
$? ". sid"
sz = dk4ma_size_t_add(
dk4ma_size_t_add(
1,
dk4strw_len(dk4user_kw[0]),
&er
),
dk4ma_size_t_add(
dk4strw_len(dk4user_kw[1]),
dk4strw_len(pStringSid),
&er
),
&er
);
if (DK4_E_NONE == er.ec) { $? ". size calc 1 ok"
(void)dk4ma_size_t_mul(sizeof(wchar_t), sz, &er);
if (DK4_E_NONE == er.ec) { $? ". size calc 2 ok"
keyname = dk4mem_calloc(sizeof(wchar_t),sz,&er);
if (NULL != keyname) { $? ". calloc ok"
(void)dk4strw_cpy_s(keyname, sz, dk4user_kw[0], NULL);
(void)dk4strw_cat_s(keyname, sz, dk4user_kw[1], NULL);
(void)dk4strw_cat_s(keyname, sz, pStringSid, NULL);
wrkey = dk4wreg_open_key_wc(DK4_WREGKEY_HKLM, keyname, 0, &er);
if (NULL != wrkey) { $? ". key opened"
back = dk4wreg_get_expanded_string_wc(
wrkey,
dk4user_kw[2],
pdst, szdst,
b1, DK4_SIZEOF(b1,wchar_t),
b2, (DK4_SIZEOF(b2,wchar_t)-2),
&er
); $? ". back = %d", back
dk4wreg_close_key(wrkey);
} else { $? "! registry key"
/* ERROR: Failed to open key (reported) */
}
dk4mem_free(keyname);
} else { $? "! memory"
/* ERROR: Memory (reported) */
}
} else { $? "! size calc overflow"
/* ERROR: Overflow in size calculation (reported) */
}
} else { $? "! size calc overflow"
/* ERROR: Overflow in size calculation (reported) */
}
} else { $? "! failed to convert sid"
/* ERROR: Failed to convert SID */
dk4error_set_simple_error_code(&er, DK4_E_NOT_FOUND);
}
if (NULL != pStringSid) {
LocalFree(pStringSid);
}
} else { $? "! failed to obtain info"
/* ERROR: No user info */
}
if (NULL != pbuf4) {
NetApiBufferFree(pbuf4);
}
} else { $? "! user name too long"
/* ERROR: User name too long */
dk4error_set_simple_error_code(&er, DK4_E_BUFFER_TOO_SMALL);
}
} else { $? "! user name not found"
/* ERROR: User name not found */
}
if (0 == back) {
dk4error_copy(erp, &er);
}
$? "- dk4user_get_i_ls_homedir %d", back
return back;
}
/** Find Windows home directory.
@param pdst Destination buffer pointer.
@param szdst Destination buffer size (number of wchar_t).
@param erp Error report, may be NULL.
@return 1 on success, 0 on error.
*/
static
int
dk4user_get_i_homedir(wchar_t *pdst, size_t szdst, dk4_er_t *erp)
{
dk4_er_t myerp;
wchar_t *lsn = NULL;
wchar_t *hop = NULL;
int back = 0;
$? "+ dk4user_get_i_homedir"
dk4error_init(&myerp);
back = dk4user_get_i_ls_homedir(pdst, szdst, NULL, &myerp);
$? ". back = %d", back
if ((0 == back) && (DK4_E_NONE == myerp.ec)) { $? ". attempt"
lsn = _wgetenv(dk4user_kw[4]); $? ". userprofile"
if (NULL != lsn) {
back = dk4strw_cpy_s(pdst, szdst, lsn, &myerp);
$? ". back = %d", back
} else { $? "! userprofile"
}
}
if ((0 == back) && (DK4_E_NONE == myerp.ec)) { $? ". attempt"
lsn = _wgetenv(dk4user_kw[5]);
hop = _wgetenv(dk4user_kw[6]);
if ((NULL != lsn) && (NULL != hop)) { $? ". drive / path"
if (0 != dk4strw_cpy_s(pdst, szdst, lsn, &myerp)) {
back = dk4strw_cat_s(pdst, szdst, hop, &myerp);
$? ". back = %d", back
} else { $? "! too long"
}
} else { $? "! drive / path"
}
}
if ((0 == back) && (DK4_E_NONE == myerp.ec)) { $? ". attempt"
lsn = _wgetenv(dk4user_kw[3]);
if (NULL != lsn) { $? ". env ok"
back = dk4user_get_i_ls_homedir(pdst, szdst, lsn, &myerp);
$? ". back = %d", back
}
}
if ((0 == back) && (DK4_E_NONE == myerp.ec)) { $? ". attempt"
if (NULL != lsn) { $? ". lsn"
if (L'\\' == lsn[0]) {
if (L'\\' == lsn[1]) {
back = dk4user_get_i_ls_homedir(pdst, szdst, &(lsn[2]), &myerp);
$? ". back = %d", back
} else { $? "! lsn[1]"
}
} else { $? "! lsn[0]"
}
} else { $? "! lsn"
}
}
if ((0 == back) && (DK4_E_NONE == myerp.ec)) {
dk4error_set_simple_error_code(&myerp, DK4_E_NOT_FOUND);
}
if (0 == back) {
dk4error_copy(erp, &myerp);
} $? "- dk4user_get_i_homedir %d", back
return back;
}
#endif
int
dk4user_get_homedir(dkChar *pdst, size_t szdst, int eff, dk4_er_t *erp)
{
#if DK4_ON_WINDOWS
/* +++++ Windows +++++ */
#if DK4_CHAR_SIZE == 1
wchar_t homew[DK4_MAX_PATH];
#endif
int back = 0;
$? "+ dk4user_get_homedir"
if ((NULL != pdst) && (0 < szdst)) { $? ". arguments"
*pdst = dkT('\0');
#if DK4_CHAR_SIZE > 1
$? ". wchar_t"
back = dk4user_get_i_homedir(pdst, szdst, erp);
#else
$? ". char"
if (0 != dk4user_get_i_homedir(homew, DK4_SIZEOF(homew,wchar_t), erp)) {
back = dk4recode_utf16_to_ansi(pdst, szdst, homew, erp);
}
#endif
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} $? "- dk4user_get_homedir %d", back
return back;
/* ----- Windows ----- */
#else
/* +++++ non-Windows +++++ */
#if DK4_CHAR_SIZE > 1
/* +++++ non-Windows wchar_t +++++ */
dk4error_set_simple_error_code(erp, DK4_E_NOT_SUPPORTED);
return 0;
/* ----- non-Windows wchar_t ----- */
#else
/* +++++ non-Windows char +++++ */
struct passwd *pwent;
uid_t uid;
int back = 0;
$? "+ dk4user_get_homedir (non-windows, char)"
if ((NULL != pdst) && (0 < szdst)) {
if (0 != eff) { uid = geteuid(); } else { uid = getuid(); }
pwent = getpwuid(uid);
if (NULL != pwent) {
if (NULL != pwent->pw_dir) {
if (0 != dk4str8_cpy_s(pdst, szdst, pwent->pw_dir, erp)) {
back = 1;
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_NOT_FOUND);
}
} else {
dk4error_set_simple_error_code(erp, DK4_E_INVALID_ARGUMENTS);
} $? "- dk4user_get_homedir (non-windows, char) %d", back
return back;
/* ----- non-Windows char ----- */
#endif
/* ----- non-Windows ----- */
#endif
}