%% 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 }