WindowsXP-SP1/ds/adsi/nw312/nw3utils.cxx

2426 lines
56 KiB
C++

#include "NWCOMPAT.hxx"
#pragma hdrstop
//----------------------------------------------------------------------------
//
// Function: NWApiGetProperty
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGetProperty(
BSTR bstrObjectName,
LPSTR lpszPropertyName,
NWOBJ_TYPE dwOT_ID,
NWCONN_HANDLE hConn,
LPP_RPLY_SGMT_LST lppReplySegment,
LPDWORD pdwNumSegment
)
{
CHAR szObjectName[(OBJ_NAME_SIZE + 1)*2];
NWFLAGS pucMoreFlag = 0;
NWFLAGS pucPropFlag = 0;
unsigned char ucSegment = 1;
LP_RPLY_SGMT_LST lpHeadReplySegment = NULL;
LP_RPLY_SGMT_LST lpTempReplySegment = NULL;
LP_RPLY_SGMT_LST lpTemp = NULL;
HRESULT hr = S_OK;
NWCCODE usRet = 0;
//
// lppReplySegment is assumed to be NULL.
//
ADsAssert((*lppReplySegment) == NULL);
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(bstrObjectName) > OBJ_NAME_SIZE) {
hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
}
UnicodeToAnsiString(
bstrObjectName,
szObjectName,
0
);
//
// Initialize first node of the list and set up temp traversal pointer.
//
INIT_RPLY_SGMT(lpTempReplySegment);
lpHeadReplySegment = lpTempReplySegment;
//
// Read & dump property values into linked-list.
//
do {
usRet = NWCReadPropertyValue(
hConn,
szObjectName,
dwOT_ID,
lpszPropertyName,
ucSegment,
lpTempReplySegment->Segment,
&pucMoreFlag,
&pucPropFlag
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
if (pucMoreFlag) {
INIT_RPLY_SGMT(lpTempReplySegment->lpNext);
lpTempReplySegment = lpTempReplySegment->lpNext;
ucSegment++;
}
} while(pucMoreFlag);
//
// Return the resulting linked-list.
//
*lppReplySegment = lpHeadReplySegment;
*pdwNumSegment = ucSegment;
error:
if (FAILED(hr) && lpHeadReplySegment) {
DELETE_LIST(lpHeadReplySegment);
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiGetFileServerVersionInfo
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGetFileServerVersionInfo(
NWCONN_HANDLE hConn,
VERSION_INFO *pVersionInfo
)
{
NWCCODE usRet = SUCCESSFUL;
HRESULT hr = S_OK;
usRet = NWCGetFileServerVersionInfo(
hConn,
pVersionInfo
);
hr = HRESULT_FROM_NWCCODE(usRet);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiIsObjectInSet
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiIsObjectInSet(
NWCONN_HANDLE hConn,
LPWSTR lpszObjectName,
NWOBJ_TYPE wObjType,
LPSTR lpszPropertyName,
LPSTR lpszMemberName,
NWOBJ_TYPE wMemberType
)
{
CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
lpszObjectName,
szAnsiObjectName,
0
);
//
// Call NWCIsObjectInSet.
//
usRet = NWCIsObjectInSet(
hConn,
szAnsiObjectName,
wObjType,
lpszPropertyName,
lpszMemberName,
wMemberType
);
hr = HRESULT_FROM_NWCCODE(usRet);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiGetObjectID
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGetObjectID(
NWCONN_HANDLE hConn,
LPWSTR lpszObjectName,
NWOBJ_TYPE wObjType,
NWOBJ_ID *pObjectID
)
{
CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
lpszObjectName,
szAnsiObjectName,
0
);
//
// Get Object's ID.
//
usRet = NWCGetObjectID(
hConn,
szAnsiObjectName,
wObjType,
pObjectID
);
hr = HRESULT_FROM_NWCCODE(usRet);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiGroupGetMembers
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGroupGetMembers(
NWCONN_HANDLE hConn,
LPWSTR szGroupName,
LPBYTE *lppBuffer
)
{
DWORD dwNumSegment = 0;
HRESULT hr = S_OK;
DWORD i;
LP_RPLY_SGMT_LST lpTemp = NULL;
LP_RPLY_SGMT_LST lpReplySegment = NULL;
//
// Assert
//
ADsAssert(*lppBuffer == NULL);
//
// Get GROUP_MEMBERS.
//
hr = NWApiGetProperty(
szGroupName,
NW_PROP_GROUP_MEMBERS,
OT_USER_GROUP,
hConn,
&lpReplySegment,
&dwNumSegment
);
BAIL_ON_FAILURE(hr);
//
// Pack returned linked list into buffer.
//
*lppBuffer = (LPBYTE) AllocADsMem(
dwNumSegment * REPLY_VALUE_SIZE
);
if (!(*lppBuffer)) {
RRETURN(E_OUTOFMEMORY);
}
lpTemp = lpReplySegment;
for (i = 0; i < dwNumSegment; i++) {
memcpy(
*lppBuffer + i * REPLY_VALUE_SIZE,
lpTemp->Segment,
REPLY_VALUE_SIZE
);
lpTemp = lpTemp->lpNext;
}
error:
//
// Clean up.
//
lpTemp = NULL;
if (lpReplySegment) {
DELETE_LIST(lpReplySegment);
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiAddGroupMember
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiAddGroupMember(
NWCONN_HANDLE hConn,
LPWSTR pszGroupName,
LPWSTR pszMemberName
)
{
CHAR szGroupName[(OBJ_NAME_SIZE + 1)*2];
CHAR szMemberName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(pszGroupName) > OBJ_NAME_SIZE) {
hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
}
if (wcslen(pszMemberName) > OBJ_NAME_SIZE) {
hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
}
UnicodeToAnsiString(
pszGroupName,
szGroupName,
0
);
UnicodeToAnsiString(
pszMemberName,
szMemberName,
0
);
//
// Modify GROUP_MEMBERS property of the group to include the new member.
//
usRet = NWCAddObjectToSet(
hConn,
szGroupName,
OT_USER_GROUP,
"GROUP_MEMBERS",
szMemberName,
OT_USER
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
//
// Modify GROUPS_I'M_IN property of the new member to reflect its included
// in the new group.
//
usRet = NWCAddObjectToSet(
hConn,
szMemberName,
OT_USER,
"GROUPS_I'M_IN",
szGroupName,
OT_USER_GROUP
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
//
// Modify SECURITY_EQUALS property of the new member to equate its security
// to that of the new group it just joined.
//
usRet = NWCAddObjectToSet(
hConn,
szMemberName,
OT_USER,
"SECURITY_EQUALS",
szGroupName,
OT_USER_GROUP
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiRemoveGroupMember
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiRemoveGroupMember(
NWCONN_HANDLE hConn,
LPWSTR pszGroupName,
LPWSTR pszMemberName
)
{
CHAR szGroupName[(OBJ_NAME_SIZE + 1)*2];
CHAR szMemberName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(pszGroupName) > OBJ_NAME_SIZE) {
hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
}
if (wcslen(pszMemberName) > OBJ_NAME_SIZE) {
hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
}
UnicodeToAnsiString(
pszGroupName,
szGroupName,
0
);
UnicodeToAnsiString(
pszMemberName,
szMemberName,
0
);
//
// Modify SECURITY_EQUALS property of the removed member to break its
// security tie with the group it joined.
//
usRet = NWCDeleteObjectFromSet(
hConn,
szMemberName,
OT_USER,
"SECURITY_EQUALS",
szGroupName,
OT_USER_GROUP
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
//
// Modify GROUPS_I'M_IN property of the new member to reflect it is not
// included in the group anymore.
//
usRet = NWCDeleteObjectFromSet(
hConn,
szMemberName,
OT_USER,
"GROUPS_I'M_IN",
szGroupName,
OT_USER_GROUP
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
//
// Modify GROUP_MEMBERS property of the group to remove the member.
//
usRet = NWCDeleteObjectFromSet(
hConn,
szGroupName,
OT_USER_GROUP,
"GROUP_MEMBERS",
szMemberName,
OT_USER
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiGetLOGIN_CONTROL
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGetLOGIN_CONTROL(
NWCONN_HANDLE hConn,
LPWSTR lpszUserName,
LPLC_STRUCTURE lpLoginCtrlStruct
)
{
DWORD dwNumSegment = 0;
HRESULT hr = S_OK;
LP_RPLY_SGMT_LST lpReplySegment = NULL;
LP_RPLY_SGMT_LST lpTemp = NULL;
hr = NWApiGetProperty(
lpszUserName,
NW_PROP_LOGIN_CONTROL,
OT_USER,
hConn,
&lpReplySegment,
&dwNumSegment
);
BAIL_ON_FAILURE(hr);
*lpLoginCtrlStruct = *((LPLC_STRUCTURE) lpReplySegment->Segment);
error:
if (lpReplySegment) {
DELETE_LIST(lpReplySegment);
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiSetDefaultAcctExpDate
//
// Synopsis: This function looks at the local time and returns a default value
// for an account expiration date in a variant date.
//
//----------------------------------------------------------------------------
HRESULT
NWApiSetDefaultAcctExpDate(
DOUBLE * pdTime,
SYSTEMTIME SysTime
)
{
DOUBLE vTime;
HRESULT hr = S_OK;
//
// According to SysCon, the default account expiration date is the first day
// of the following month.
//
if (SysTime.wMonth == 12) {
SysTime.wMonth = 1;
}
else {
SysTime.wMonth++;
}
SysTime.wDay = 1;
//
// Subtract 1980 from wYear for NWApiMakeVariantTime.
//
SysTime.wYear -= 1980;
hr = NWApiMakeVariantTime(
&vTime,
SysTime.wDay,
SysTime.wMonth,
SysTime.wYear,
0,0,0
);
BAIL_ON_FAILURE(hr);
*pdTime = vTime;
error:
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiUserAsSupervisor
//
// Synopsis: This functions turns the user into one of the supervisors if TRUE
// is passed. User's supervisor privilege is removed otherwise.
//
//----------------------------------------------------------------------------
HRESULT
NWApiUserAsSupervisor(
NWCONN_HANDLE hConn,
LPWSTR lpszUserName,
BOOL fSupervisor
)
{
CHAR szUserName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(lpszUserName) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
lpszUserName,
szUserName,
0
);
//
// Make it a supervisor.
//
if (fSupervisor == TRUE) {
usRet = NWCAddObjectToSet(
hConn,
szUserName,
OT_USER,
"SECURITY_EQUALS",
"SUPERVISOR",
OT_USER
);
}
//
// Remove supervisor privilege.
//
else {
usRet = NWCDeleteObjectFromSet(
hConn,
szUserName,
OT_USER,
"SECURITY_EQUALS",
"SUPERVISOR",
OT_USER
);
}
hr = HRESULT_FROM_NWCCODE(usRet);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiGetVolumeNumber
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGetVolumeNumber(
NWCONN_HANDLE hConn,
LPWSTR lpszVolumeName,
NWVOL_NUM *pVolumeNumber
)
{
CHAR szVolumeName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(lpszVolumeName) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
lpszVolumeName,
szVolumeName,
0
);
//
// Get Volume's number.
//
usRet = NWCGetVolumeNumber(
hConn,
szVolumeName,
pVolumeNumber
);
hr = HRESULT_FROM_NWCCODE(usRet);
//
// Return.
//
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiGetVolumeName
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGetVolumeName(
NWCONN_HANDLE hConn,
NWVOL_NUM bVolNum,
LPWSTR *lppszVolName
)
{
CHAR szVolumeName[OBJ_NAME_SIZE + 1];
HRESULT hr = S_OK;
LPWSTR lpszTemp = NULL;
NWCCODE usRet = SUCCESSFUL;
//
// Get Volume's name.
//
usRet = NWCGetVolumeName(
hConn,
bVolNum,
szVolumeName
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
//
// Convert result into Unicode.
//
lpszTemp = AllocateUnicodeString(szVolumeName);
if (!lpszTemp) {
RRETURN(E_OUTOFMEMORY);
}
*lppszVolName = AllocADsStr(lpszTemp);
if (!(*lppszVolName)) {
RRETURN(E_OUTOFMEMORY);
}
FreeUnicodeString(lpszTemp);
//
// Return.
//
RRETURN(hr);
error:
*lppszVolName = NULL;
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiEnumJobs
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiEnumJobs(
HANDLE hPrinter,
DWORD dwFirstJob,
DWORD dwNoJobs,
DWORD dwLevel,
LPBYTE *lplpbJobs,
DWORD *pcbBuf,
LPDWORD lpdwReturned
)
{
BOOL fStatus = TRUE;
HRESULT hr = S_OK;
fStatus = WinNTEnumJobs(
hPrinter,
dwFirstJob,
dwNoJobs,
dwLevel,
lplpbJobs,
pcbBuf,
lpdwReturned
);
if (fStatus == FALSE) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiGetPrinter
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiGetPrinter(
HANDLE hPrinter,
DWORD dwLevel,
LPBYTE *lplpbPrinters
)
{
BOOL fStatus = TRUE;
HRESULT hr = S_OK;
fStatus = WinNTGetPrinter(
hPrinter,
dwLevel,
lplpbPrinters
);
if (fStatus == FALSE) {
hr = HRESULT_FROM_WIN32(GetLastError());
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiUncFromADsPath
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiUncFromADsPath(
LPWSTR lpszADsPath,
LPWSTR lpszUncName
)
{
HRESULT hr;
POBJECTINFO pObjectInfo = NULL;
hr = BuildObjectInfo(lpszADsPath,
&pObjectInfo );
BAIL_ON_FAILURE(hr);
wsprintf(
lpszUncName,
L"\\\\%s\\%s",
pObjectInfo->ComponentArray[0],
pObjectInfo->ComponentArray[1]
);
error:
if(pObjectInfo){
FreeObjectInfo(pObjectInfo);
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiMakeUserInfo
//
// Synopsis: This function is very provider specific.
//
//----------------------------------------------------------------------------
HRESULT
NWApiMakeUserInfo(
LPWSTR lpszBinderyName,
LPWSTR lpszUserName,
LPWSTR lpszPassword,
PNW_USER_INFO pNwUserInfo
)
{
HRESULT hr = S_OK;
NW_USER_INFO NwUserInfo = {NULL, NULL, NULL, NULL};
hr = NWApiGetBinderyHandle(
&NwUserInfo.hConn,
lpszBinderyName
);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(lpszBinderyName, &NwUserInfo.lpszBinderyName);
BAIL_ON_FAILURE(hr);
hr = ADsAllocString(lpszUserName, &NwUserInfo.lpszUserName);
BAIL_ON_FAILURE(hr);
if (lpszPassword) {
hr = ADsAllocString(lpszPassword, &NwUserInfo.lpszPassword);
BAIL_ON_FAILURE(hr);
}
//
// Return.
//
*pNwUserInfo = NwUserInfo;
RRETURN(hr);
error:
if (NwUserInfo.lpszBinderyName)
ADsFreeString(NwUserInfo.lpszBinderyName);
if (NwUserInfo.lpszUserName)
ADsFreeString(NwUserInfo.lpszUserName);
if (NwUserInfo.lpszPassword)
ADsFreeString(NwUserInfo.lpszPassword);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiFreeUserInfo
//
// Synopsis: This function is very provider specific.
//
//----------------------------------------------------------------------------
HRESULT
NWApiFreeUserInfo(
PNW_USER_INFO pNwUserInfo
)
{
HRESULT hr = S_OK;
if (pNwUserInfo->lpszBinderyName) {
ADsFreeString(pNwUserInfo->lpszBinderyName);
pNwUserInfo->lpszBinderyName = NULL ;
}
if (pNwUserInfo->lpszUserName) {
ADsFreeString(pNwUserInfo->lpszUserName);
pNwUserInfo->lpszUserName = NULL;
}
if (pNwUserInfo->lpszPassword) {
ADsFreeString(pNwUserInfo->lpszPassword);
pNwUserInfo->lpszPassword = NULL;
}
if (pNwUserInfo->hConn) {
hr = NWApiReleaseBinderyHandle(
pNwUserInfo->hConn
);
BAIL_ON_FAILURE(hr);
}
error:
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiCreateUser
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiCreateUser(
PNW_USER_INFO pNwUserInfo
)
{
HRESULT hr = S_OK;
HRESULT hrTemp = S_OK;
NTSTATUS Status = STATUS_SUCCESS;
NWCCODE usRet = SUCCESSFUL;
NWCONN_HANDLE hConn = NULL;
NWOBJ_ID UserObjectID;
UCHAR ChallengeKey[8];
UCHAR NewKeyedPassword[17];
UCHAR ValidationKey[8];
WCHAR szTemp[MAX_PATH];
//
// "Create Bindery Object" - user object. This user object is going to be
// static, with access equals to logged read, supervisor write.
//
hr = NWApiCreateBinderyObject(
pNwUserInfo->hConn,
pNwUserInfo->lpszUserName,
OT_USER,
BF_STATIC,
BS_LOGGED_READ | BS_SUPER_WRITE
);
BAIL_ON_FAILURE(hr);
//
// Add user password.
//
hr = NWApiSetUserPassword(
pNwUserInfo,
&UserObjectID,
NULL // no old passwd - this is a SET
);
BAIL_ON_FAILURE(hr);
//
// Create necessary bindery property to facilitate the addition of this user
// to the group EVERYONE.
//
hr = NWApiCreateProperty(
pNwUserInfo->hConn,
pNwUserInfo->lpszUserName,
OT_USER,
"GROUPS_I'M_IN",
BF_SET
);
BAIL_ON_FAILURE(hr);
hr = NWApiCreateProperty(
pNwUserInfo->hConn,
pNwUserInfo->lpszUserName,
OT_USER,
"SECURITY_EQUALS",
BF_SET
);
BAIL_ON_FAILURE(hr);
//
// Add this user to the group EVERYONE.
// (okay if this fails, EVERYONE might not exist)
//
wcscpy(szTemp, L"EVERYONE");
hrTemp = NWApiAddGroupMember(
pNwUserInfo->hConn,
szTemp,
pNwUserInfo->lpszUserName
);
//
// Create mail directory and login files.
// (okay if this fails)
//
hrTemp = NWApiCreateMailDirectory(
pNwUserInfo,
UserObjectID
);
//
// Create LOGIN_CONTROL & ACCOUNT_BALANCE property for the user. Values
// from USER_DEFAULTS are used as default.
//
hr = NWApiSetLoginCtrlAndAcctBalance(
pNwUserInfo
);
BAIL_ON_FAILURE(hr);
error:
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiDeleteUser
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiDeleteUser(
POBJECTINFO pObjectInfo
)
{
BOOL err = TRUE;
DWORD dwErr = 0;
HRESULT hr = S_OK;
NWCONN_HANDLE hConn = NULL;
NWOBJ_ID ObjectID;
WCHAR szPath[MAX_PATH];
//
// Open a handle to the bindery.
//
hr = NWApiGetBinderyHandle(
&hConn,
pObjectInfo->ComponentArray[0]
);
BAIL_ON_FAILURE(hr);
//
// Get the user's ObjectID which is needed to compose the path name of LOGIN
// and LOGIN.OS2.
//
hr = NWApiGetObjectID(
hConn,
pObjectInfo->ComponentArray[1],
OT_USER,
&ObjectID
);
BAIL_ON_FAILURE(hr);
//
// Delete SYS:MAIL\<JOBID>\LOGIN. If the file is not found, that's OK, as
// long as it is not there.
//
wsprintf(
szPath,
L"\\\\%s\\SYS\\MAIL\\%X\\LOGIN",
pObjectInfo->ComponentArray[0],
dwSWAP(ObjectID)
);
err = DeleteFile(szPath);
//
// Remove any error checking for the cleanup of
// files. If they do exist, and we do clean them up
// great. But otherwise Win95 chokes on us.
//
//
// Delete SYS:MAIL\<JOBID>\LOGIN.OS2. If the file is not found, that's OK,
// as long as it is not there.
//
wsprintf(
szPath,
L"\\\\%s\\SYS\\MAIL\\%X\\LOGIN.OS2",
pObjectInfo->ComponentArray[0],
dwSWAP(ObjectID)
);
err = DeleteFile(szPath);
//
// Remove any error checking for the cleanup of
// files. If they do exist, and we do clean them up
// great. But otherwise Win95 chokes on us.
//
//
// Delete SYS:MAIL\<JOBID>.
//
wsprintf(
szPath,
L"\\\\%s\\SYS\\MAIL\\%X",
pObjectInfo->ComponentArray[0],
dwSWAP(ObjectID)
);
err = RemoveDirectory(szPath);
//
// Remove any error checking for the cleanup of
// files. If they do exist, and we do clean them up
// great. But otherwise Win95 chokes on us.
//
//
// Delete the user object.
//
hr = NWApiDeleteBinderyObject(
hConn,
pObjectInfo->ComponentArray[1],
OT_USER
);
BAIL_ON_FAILURE(hr);
error:
NWApiReleaseBinderyHandle(hConn);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiCreateBinderyObject
//
// Synopsis: This function create the specified object in the specified NetWare
// bindery. It returns S_OK if the object alread exist.
//
//----------------------------------------------------------------------------
HRESULT
NWApiCreateBinderyObject(
NWCONN_HANDLE hConn,
LPWSTR lpszObjectName,
NWOBJ_TYPE wObjType,
NWFLAGS ucObjectFlags,
NWFLAGS usObjSecurity
)
{
CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
lpszObjectName,
szAnsiObjectName,
0
);
//
// Create a Static object with LOGGED_READ & SUPERVISOR_WRITE.
//
usRet = NWCCreateObject(
hConn,
szAnsiObjectName,
wObjType,
BF_STATIC,
BS_LOGGED_READ | BS_SUPER_WRITE
);
//
// If an error occured, check if it is OBJECT_ALREADY_EXISTS. If it is,
// treat it as no error.
//
if (usRet) {
if (usRet == OBJECT_ALREADY_EXISTS) {
usRet = SUCCESSFUL;
}
}
//
// Return.
//
hr = HRESULT_FROM_NWCCODE(usRet);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiDeleteBinderyObject
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiDeleteBinderyObject(
NWCONN_HANDLE hConn,
LPWSTR lpszObjectName,
NWOBJ_TYPE wObjType
)
{
CHAR szAnsiObjectName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(lpszObjectName) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
lpszObjectName,
szAnsiObjectName,
0
);
//
// Delete the object from the bindery.
//
usRet = NWCDeleteObject(
hConn,
szAnsiObjectName,
wObjType
);
//
// Return.
//
hr = HRESULT_FROM_NWCCODE(usRet);
RRETURN(hr);
}
#define NW_MAX_PASSWORD_LEN 256
//----------------------------------------------------------------------------
//
// Function: NWApiSetUserPassword
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiSetUserPassword(
PNW_USER_INFO pNwUserInfo,
DWORD *pdwUserObjID,
LPWSTR pszOldPassword
)
{
CHAR szAnsiUserName[(OBJ_NAME_SIZE + 1)*2];
CHAR szAnsiPassword[(NW_MAX_PASSWORD_LEN + 1)*2];
CHAR szAnsiOldPassword[(NW_MAX_PASSWORD_LEN + 1)*2];
CHAR Buffer[128];
DWORD err = 0;
HRESULT hr = S_OK;
LC_STRUCTURE LoginCtrl;
NTSTATUS NtStatus;
UCHAR ChallengeKey[8];
UCHAR ucMoreFlag;
UCHAR ucPropFlag;
WCHAR szOldPasswordCopy[NW_MAX_PASSWORD_LEN + 1];
if ( !pNwUserInfo ||
!(pNwUserInfo->lpszUserName) ||
!(pNwUserInfo->lpszPassword) ) {
hr = E_INVALIDARG ;
BAIL_ON_FAILURE(hr);
}
if ( (wcslen(pNwUserInfo->lpszUserName) > OBJ_NAME_SIZE) ||
(wcslen(pNwUserInfo->lpszPassword) > NW_MAX_PASSWORD_LEN) ||
( pszOldPassword && (wcslen(pszOldPassword) > NW_MAX_PASSWORD_LEN)) ) {
hr = E_INVALIDARG;
BAIL_ON_FAILURE(hr);
}
//
// Convert UNICODE into ANSI representation required by NW APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
err = UnicodeToAnsiString(
pNwUserInfo->lpszUserName,
szAnsiUserName,
0
);
if (!err) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
_wcsupr(pNwUserInfo->lpszPassword) ;
err = UnicodeToAnsiString(
pNwUserInfo->lpszPassword,
szAnsiPassword,
0
);
if (!err) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
if (pszOldPassword) {
wcscpy(szOldPasswordCopy, pszOldPassword);
_wcsupr(szOldPasswordCopy) ;
err = UnicodeToAnsiString(
szOldPasswordCopy,
szAnsiOldPassword,
0
);
if (!err) {
hr = E_FAIL;
BAIL_ON_FAILURE(hr);
}
}
else {
szAnsiOldPassword[0] = 0 ;
}
//
// Get challenge key.
//
err = NWApiMapNtStatusToDosError(
NWPGetChallengeKey(
pNwUserInfo->hConn,
ChallengeKey
));
if (!err) {
//
// For NetWare 4.x servers, this has to be done after the
// NWPGetChallengeKey so that the object id returned can be used to
// encrypt the password. 4.x bindery emulation might return different
// object ids for some users depending on whether the NWPGetChallengeKey
// is called beforehand.
//
err = NWApiMapNtStatusToDosError(
NWPGetObjectID(
pNwUserInfo->hConn,
szAnsiUserName,
OT_USER,
pdwUserObjID
));
}
if (!err) {
//
// The old password and object ID make up the 17-byte Vold. This is used
// later to form the 17-byte Vc for changing password on the server.
//
UCHAR ValidationKey[8];
UCHAR NewKeyedPassword[17];
EncryptChangePassword(
(PUCHAR) szAnsiOldPassword,
(PUCHAR) szAnsiPassword,
*pdwUserObjID,
ChallengeKey,
ValidationKey,
NewKeyedPassword
);
err = NWApiMapNtStatusToDosError(
NWPChangeObjectPasswordEncrypted(
pNwUserInfo->hConn,
szAnsiUserName,
OT_USER,
ValidationKey,
NewKeyedPassword
));
}
//
// Return.
//
hr = HRESULT_FROM_WIN32(err);
error:
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiCreateMailDirectory
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiCreateMailDirectory(
PNW_USER_INFO pNwUserInfo,
NWOBJ_ID UserObjID
)
{
BYTE szPath[(MAX_PATH + 1) * sizeof(WCHAR)];
CHAR szUserObjID[255];
DWORD err = 0;
HRESULT hr = S_OK;
//
// Make path.
//
_ltoa(
dwSWAP(UserObjID),
szUserObjID,
16
);
strcpy((char *) szPath, "SYS:\\MAIL\\");
strcat((char *) szPath, szUserObjID);
//
// Create a directory with Maximum rights mask.
//
err = NWApiMapNtStatusToDosError(
NWPCreateDirectory(
pNwUserInfo->hConn,
0,
(char *) szPath,
0xFF // From SysCon --- Max. access rights for directory
)); // = Full Access
if ( !err ) {
//
// Add a trustee with all rights except PARENTAL right.
//
err = NWApiMapNtStatusToDosError(
NWPAddTrustee(
pNwUserInfo->hConn,
0,
(char *) szPath,
UserObjID,
0xDF // From SysCon --- Trustee has all rights
)); // EXCEPT parental rights (right to create/
// delete subdirs, make others trustees)
//
// Create a Login file.
//
if ( !err ) {
HANDLE hFile;
wsprintfW(
(LPWSTR) szPath,
L"\\\\%ws\\SYS\\MAIL\\%X\\LOGIN",
pNwUserInfo->lpszBinderyName,
dwSWAP(UserObjID)
);
hFile = CreateFile(
(LPWSTR) szPath,
GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0
);
if ( hFile == INVALID_HANDLE_VALUE ) {
err = GetLastError();
}
if ( !err )
CloseHandle( hFile );
//
// Create a Login.os2 file.
//
wsprintfW(
(LPWSTR) szPath,
L"\\\\%ws\\SYS\\MAIL\\%X\\LOGIN.OS2",
pNwUserInfo->lpszBinderyName,
dwSWAP(UserObjID)
);
hFile = CreateFile(
(LPWSTR) szPath,
GENERIC_WRITE,
0,
NULL,
OPEN_ALWAYS,
FILE_ATTRIBUTE_NORMAL,
0
);
if ( hFile == INVALID_HANDLE_VALUE ) {
err = GetLastError();
}
if ( !err )
CloseHandle( hFile );
}
}
// err == 255 == "FAILURE"
// might be used to indicate directory already exists,
// but also used to signal generic failure
hr = HRESULT_FROM_WIN32(err);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiSetLoginCtrlAndAcctBalance
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiSetLoginCtrlAndAcctBalance(
PNW_USER_INFO pNwUserInfo
)
{
ACCT_BALANCE AccountBalance;
DWORD dwNumSegment;
HRESULT hr = S_OK;
int i = 0;
LC_STRUCTURE LoginCtrl;
LP_RPLY_SGMT_LST lpReplySegment = NULL;
LP_RPLY_SGMT_LST lpTemp = NULL;
USER_DEFAULT UserDefault;
WCHAR szTemp[MAX_PATH];
//
// Get Supervisor's USER_DEFAULTS.
//
wcscpy(szTemp, NW_PROP_SUPERVISORW);
hr = NWApiGetProperty(
szTemp,
NW_PROP_USER_DEFAULTS,
OT_USER,
pNwUserInfo->hConn,
&lpReplySegment,
&dwNumSegment
);
if (SUCCEEDED(hr)) {
UserDefault = *((LPUSER_DEFAULT) lpReplySegment->Segment);
//
// Put default values into LoginCtrl.
//
LoginCtrl.byAccountExpires[0] = UserDefault.byAccountExpiresYear;
LoginCtrl.byAccountExpires[1] = UserDefault.byAccountExpiresMonth;
LoginCtrl.byAccountExpires[2] = UserDefault.byAccountExpiresDay;
LoginCtrl.byAccountDisabled = 0;
LoginCtrl.byPasswordExpires[0] = 85;
LoginCtrl.byPasswordExpires[1] = 01;
LoginCtrl.byPasswordExpires[2] = 01;
LoginCtrl.byGraceLogins = UserDefault.byGraceLoginReset;
LoginCtrl.wPasswordInterval = UserDefault.wPasswordInterval;
LoginCtrl.byGraceLoginReset = UserDefault.byGraceLoginReset;
LoginCtrl.byMinPasswordLength = UserDefault.byMinPasswordLength;
LoginCtrl.wMaxConnections = UserDefault.wMaxConnections;
LoginCtrl.byRestrictions = UserDefault.byRestrictions;
LoginCtrl.byUnused = 0;
LoginCtrl.lMaxDiskBlocks = UserDefault.lMaxDiskBlocks;
LoginCtrl.wBadLogins = 0;
LoginCtrl.lNextResetTime = 0;
for (i = 0; i < 42; i++) {
LoginCtrl.byLoginTimes[i] = UserDefault.byLoginTimes[i];
}
for (i = 0; i < 6; i++) {
LoginCtrl.byLastLogin[i] = 0;
}
for (i = 0; i < 12; i++) {
LoginCtrl.byBadLoginAddr[i] = 0;
}
LoginCtrl.byGraceLogins = LoginCtrl.byGraceLoginReset;
//
// Put default values into AccountBalance.
//
AccountBalance.lBalance = UserDefault.lBalance;
AccountBalance.lCreditLimit = UserDefault.lCreditLimit;
//
// Write LOGIN_CONTROL property.
//
hr = NWApiWriteProperty(
pNwUserInfo->hConn,
pNwUserInfo->lpszUserName,
OT_USER,
NW_PROP_LOGIN_CONTROL,
(LPBYTE) &LoginCtrl
);
BAIL_ON_FAILURE(hr);
//
// Write ACCOUNT_BALANCE property.
//
hr = NWApiWriteProperty(
pNwUserInfo->hConn,
pNwUserInfo->lpszUserName,
OT_USER,
NW_PROP_ACCOUNT_BALANCE,
(LPBYTE) &AccountBalance
);
BAIL_ON_FAILURE(hr);
}
//
// SUPERVISOR may not exist, or may not have USER_DEFAULTS.
// This is okay.
//
hr = S_OK;
error:
if (lpReplySegment) {
DELETE_LIST(lpReplySegment);
}
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiCreateGroup
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiCreateGroup(
POBJECTINFO pObjectInfo
)
{
HRESULT hr = S_OK;
NWCONN_HANDLE hConn = NULL;
//
// Open a handle to the bindery.
//
hr = NWApiGetBinderyHandle(
&hConn,
pObjectInfo->ComponentArray[0]
);
BAIL_ON_FAILURE(hr);
//
// Create a group bindery object.
//
hr = NWApiCreateBinderyObject(
hConn,
pObjectInfo->ComponentArray[1],
OT_USER_GROUP,
BF_STATIC,
BS_LOGGED_READ | BS_SUPER_WRITE
);
BAIL_ON_FAILURE(hr);
//
// Create GROUP_MEMBERS property.
//
hr = NWApiCreateProperty(
hConn,
pObjectInfo->ComponentArray[1],
OT_USER_GROUP,
NW_PROP_GROUP_MEMBERS,
BF_SET
);
BAIL_ON_FAILURE(hr);
error:
NWApiReleaseBinderyHandle(hConn);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiDeleteGroup
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiDeleteGroup(
POBJECTINFO pObjectInfo
)
{
HRESULT hr = S_OK;
NWCONN_HANDLE hConn = NULL;
//
// Open a handle to the bindery.
//
hr = NWApiGetBinderyHandle(
&hConn,
pObjectInfo->ComponentArray[0]
);
BAIL_ON_FAILURE(hr);
//
// Delete the group object.
//
hr = NWApiDeleteBinderyObject(
hConn,
pObjectInfo->ComponentArray[1],
OT_USER_GROUP
);
BAIL_ON_FAILURE(hr);
error:
NWApiReleaseBinderyHandle(hConn);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiCreatePrinter
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiCreatePrinter(
POBJECTINFO pObjectInfo
)
{
CHAR szQueueName[(OBJ_NAME_SIZE + 1)*2];
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
NWCONN_HANDLE hConn = NULL;
WCHAR szTemp[MAX_PATH];
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(pObjectInfo->ComponentArray[1]) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
pObjectInfo->ComponentArray[1],
szQueueName,
0
);
//
// Open a handle to the bindery.
//
hr = NWApiGetBinderyHandle(
&hConn,
pObjectInfo->ComponentArray[0]
);
BAIL_ON_FAILURE(hr);
//
// Create a print queue object.
//
hr = NWApiCreatePrintQueue(
hConn,
pObjectInfo->ComponentArray[1]
);
BAIL_ON_FAILURE(hr);
//
// Change property security.
//
usRet = NWCChangePropertySecurity(
hConn,
szQueueName,
OT_PRINT_QUEUE,
NW_PROP_Q_OPERATORS,
BS_LOGGED_READ | BS_SUPER_WRITE
);
hr = HRESULT_FROM_NWCCODE(usRet);
BAIL_ON_FAILURE(hr);
//
// Add SUPERVISOR to Q_OPERATORS.
// (okay if this fails, maybe SUPERVISOR doesn't exist)
//
usRet = NWCAddObjectToSet(
hConn,
szQueueName,
OT_PRINT_QUEUE,
NW_PROP_Q_OPERATORS,
NW_PROP_SUPERVISOR,
OT_USER
);
//
// Add EVERYONE to Q_USERS.
// (okay if this fails, maybe EVERYONE doesn't exist)
//
usRet = NWCAddObjectToSet(
hConn,
szQueueName,
OT_PRINT_QUEUE,
NW_PROP_Q_USERS,
NW_PROP_EVERYONE,
OT_USER_GROUP
);
//
// Return.
//
error:
NWApiReleaseBinderyHandle(hConn);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiDeleteGroup
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiDeletePrinter(
POBJECTINFO pObjectInfo
)
{
HRESULT hr = S_OK;
NWCONN_HANDLE hConn = NULL;
NWOBJ_ID dwQueueID = 0;
//
// Open a handle to the bindery.
//
hr = NWApiGetBinderyHandle(
&hConn,
pObjectInfo->ComponentArray[0]
);
BAIL_ON_FAILURE(hr);
//
// Get Queue ID.
//
hr = NWApiDestroyPrintQueue(
hConn,
pObjectInfo->ComponentArray[1]
);
BAIL_ON_FAILURE(hr);
error:
NWApiReleaseBinderyHandle(hConn);
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiCreatePrintQueue
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiCreatePrintQueue(
NWCONN_HANDLE hConn,
LPWSTR lpszQueueName
)
{
CHAR szQueueName[(OBJ_NAME_SIZE + 1)*2];
DWORD dwQueueID = 0;
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Convert BSTR into an ANSI representation required by NWC APIs. "0" is
// passed to UnicodeToAnsiString when the length of the string is unknown.
//
if (wcslen(lpszQueueName) > OBJ_NAME_SIZE) {
RRETURN(E_INVALIDARG);
}
UnicodeToAnsiString(
lpszQueueName,
szQueueName,
0
);
//
// Create a print queue object.
//
usRet = NWCCreateQueue(
hConn,
NULL,
szQueueName,
OT_PRINT_QUEUE,
NW_PRINTER_PATH,
&dwQueueID
);
hr = HRESULT_FROM_NWCCODE(usRet);
//
// Return.
//
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiDestroyPrintQueue
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiDestroyPrintQueue(
NWCONN_HANDLE hConn,
LPWSTR lpszQueueName
)
{
DWORD dwQueueID = 0;
HRESULT hr = S_OK;
NWCCODE usRet = SUCCESSFUL;
//
// Get Queue ID.
//
hr = NWApiGetObjectID(
hConn,
lpszQueueName,
OT_PRINT_QUEUE,
&dwQueueID
);
BAIL_ON_FAILURE(hr);
//
// Destroy print queue.
//
usRet = NWCDestroyQueue(
hConn,
dwSWAP(dwQueueID)
);
hr = HRESULT_FROM_NWCCODE(usRet);
//
// Return.
//
error:
RRETURN(hr);
}
//----------------------------------------------------------------------------
//
// Function: NWApiMapNtStatusToDosError
//
// Synopsis: This function maps the ntstatus that was returned from the NetWare
// redirector to window errors. Similar to RtlNtStatusToDosError
// except that the special handling is done to ntstatus with netware
// facility codes.
//
// Argument: NtStatus - The ntstatus returned from NetWare rdr
//
// Return Value: WinError
//
//----------------------------------------------------------------------------
DWORD
NWApiMapNtStatusToDosError(
IN NTSTATUS NtStatus
)
{
if ( (HIWORD( NtStatus) & FACILITY_NWRDR ) == FACILITY_NWRDR )
{
if ( NtStatus == NWRDR_PASSWORD_HAS_EXPIRED )
return ERROR_PASSWORD_EXPIRED;
else
return NETWARE_GENERAL_ERROR;
}
else if ( HIWORD( NtStatus) == 0xC001 )
{
return LOWORD( NtStatus ) + NETWARE_ERROR_BASE;
}
return RtlNtStatusToDosError( NtStatus );
}
//----------------------------------------------------------------------------
//
// Function: NWApiConvertToAddressFormat
//
// Synopsis: Convert an IPX address obtain from NWApiGetProperty into the
// format specified in spec.
//
//----------------------------------------------------------------------------
HRESULT
NWApiConvertToAddressFormat(
LP_RPLY_SGMT_LST lpReplySegment,
LPWSTR *lppszAddresses
)
{
int i = 0;
LPBYTE lpBuffer = NULL;
LPWSTR lpszTemp = NULL;
WORD wSegment[NET_ADDRESS_WORD_SIZE];
//
// Put values from szReply into the wSegment array
//
lpBuffer = (LPBYTE) lpReplySegment->Segment;
for (i = 0; i < NET_ADDRESS_WORD_SIZE; i++) {
wSegment[i] = NWApiReverseWORD(*((LPWORD)lpBuffer + i));
}
//
// Put address together in the format described in spec.
//
lpszTemp = (LPWSTR) AllocADsMem((NET_ADDRESS_NUM_CHAR+1)*sizeof(WCHAR));
if (!lpszTemp) {
RRETURN(E_OUTOFMEMORY);
}
wsprintf(
lpszTemp,
L"%s:%04X%04X.%04X%04X%04X.%04X",
bstrAddressTypeString,
wSegment[0],
wSegment[1],
wSegment[2],
wSegment[3],
wSegment[4],
wSegment[5]
);
//
// Return.
//
*lppszAddresses = lpszTemp;
RRETURN(S_OK);
}
//----------------------------------------------------------------------------
//
// Function: NWApiMakeVariantTime
//
// Synopsis: This function creates a double precision variant time.
//
//----------------------------------------------------------------------------
HRESULT
NWApiMakeVariantTime(
DOUBLE * pdTime,
WORD wDay, // Day = 1..31
WORD wMonth, // Month = 1..12
WORD wYear, // Year = (19XX or 20XX) - 1980, ie. 2019 -> 39
WORD wSecond, // Second = 0..30, Second divided by 2
WORD wMinute, // Minute = 0..59
WORD wHour // Hour = 0..23
)
{
BOOL fBool = TRUE;
DOUBLE vTime = 0;
WORD wDOSDate = 0;
WORD wDOSTime = 0;
//
// Fix up parameters.
// If wDay and wMonth are 0, turn them into one.
//
if (wDay == 0) {
wDay++;
}
if (wMonth == 0) {
wMonth++;
}
//
// Shift data to correct bit as required by the DOS date & time format.
//
wMonth = wMonth << 5;
wYear = wYear << 9;
wMinute = wMinute << 5;
wHour = wHour << 11;
//
// Put them in DOS format.
//
wDOSDate = wYear | wMonth | wDay;
wDOSTime = wHour | wMinute | wSecond;
//
// Convert into VariantTime.
//
fBool = DosDateTimeToVariantTime(
wDOSDate,
wDOSTime,
&vTime
);
//
// Return.
//
if (fBool == TRUE) {
*pdTime = vTime;
RRETURN(S_OK);
}
else {
RRETURN(E_FAIL);
}
}
//----------------------------------------------------------------------------
//
// Function: NWApiBreakVariantTime
//
// Synopsis: This function interprets a double precision variant time and
// returns the day, month and year individually.
//
//----------------------------------------------------------------------------
HRESULT
NWApiBreakVariantTime(
DOUBLE daDate,
PWORD pwDay,
PWORD pwMonth,
PWORD pwYear
)
{
BOOL fBool;
DOUBLE vTime;
WORD wDOSDate = 0;
WORD wDOSTime = 0;
WORD wDay = 0;
WORD wMonth = 0;
WORD wYear = 0;
//
// Convert variant time into DOS format.
//
fBool = VariantTimeToDosDateTime(
daDate,
&wDOSDate,
&wDOSTime
);
if (fBool == FALSE) {
goto error;
}
//
// Year: bits 9-15, add 80 to wYear because 80 was subtracted from it to
// call VariantTimeToDosDateTime.
//
wYear = wDOSDate >> 9;
wYear += 80;
//
// Month: bits 5-8.
//
wMonth = (wDOSDate >> 5) - (wYear << 4);
//
// Day: bits 0-4.
//
wDay = wDOSDate - (wMonth << 5) - (wYear << 9);
//
// Return.
//
*pwDay = wDay;
*pwMonth = wMonth;
*pwYear = wYear;
RRETURN(S_OK);
error:
RRETURN(E_FAIL);
}
//----------------------------------------------------------------------------
//
// Function: NWApiReverseWORD
//
// Synopsis: This function reverse a WORD.
//
//----------------------------------------------------------------------------
WORD
NWApiReverseWORD(
WORD wWORD
)
{
LPBYTE lpbTemp = (LPBYTE) &wWORD;
BYTE bTemp;
bTemp = *lpbTemp;
*lpbTemp = *(lpbTemp + 1);
*(lpbTemp + 1) = bTemp;
return(*((LPWORD) lpbTemp));
}
//----------------------------------------------------------------------------
//
// Function: NWApiUserGetGroups
//
// Synopsis:
//
//----------------------------------------------------------------------------
HRESULT
NWApiUserGetGroups(
NWCONN_HANDLE hConn,
LPWSTR szUserName,
LPBYTE *lppBuffer
)
{
DWORD dwNumSegment = 0;
HRESULT hr = S_OK;
DWORD i;
LP_RPLY_SGMT_LST lpTemp = NULL;
LP_RPLY_SGMT_LST lpReplySegment = NULL;
//
// Assert
//
ADsAssert(*lppBuffer == NULL);
//
// Get GROUP_MEMBERS.
//
hr = NWApiGetProperty(
szUserName,
NW_PROP_USER_GROUPS,
OT_USER,
hConn,
&lpReplySegment,
&dwNumSegment
);
BAIL_ON_FAILURE(hr);
//
// Pack returned linked list into buffer.
//
*lppBuffer = (LPBYTE) AllocADsMem(
dwNumSegment * REPLY_VALUE_SIZE
);
if (!(*lppBuffer)) {
RRETURN(E_OUTOFMEMORY);
}
lpTemp = lpReplySegment;
for (i = 0; i < dwNumSegment; i++) {
memcpy(
*lppBuffer + i * REPLY_VALUE_SIZE,
lpTemp->Segment,
REPLY_VALUE_SIZE
);
lpTemp = lpTemp->lpNext;
}
error:
//
// Clean up.
//
lpTemp = NULL;
if (lpReplySegment) {
DELETE_LIST(lpReplySegment);
}
RRETURN(hr);
}