diff options
Diffstat (limited to '')
-rw-r--r-- | private/nw/convert/nwconv/usrprop.c | 592 |
1 files changed, 592 insertions, 0 deletions
diff --git a/private/nw/convert/nwconv/usrprop.c b/private/nw/convert/nwconv/usrprop.c new file mode 100644 index 000000000..c52603ee0 --- /dev/null +++ b/private/nw/convert/nwconv/usrprop.c @@ -0,0 +1,592 @@ +/*++ + +Copyright (c) 1993-1993 Microsoft Corporation + +Module Name: + + usrprop.c + +Abstract: + + This module implements QueryUserProperty() and SetUserProperty() + which read and write NetWare Properties to the UserParms field. + +Author: + + Andy Herron (andyhe) 24-May-1993 + Congpa You (CongpaY) 28-Oct-1993 Seperated SetUserProperty() and + QueryUserProperty() out from usrprop.c + in ncpsrv\svcdlls\ncpsvc\libbind, + modified the code and fixed a few + existing problems. + +Revision History: + +--*/ + +#include "nt.h" +#include "ntrtl.h" +#include "nturtl.h" +#include "ntioapi.h" +#include "windef.h" +#include "winbase.h" +#include "stdio.h" +#include "stdlib.h" +#include "winuser.h" + +#include "usrprop.h" + +#define NCP_SET 0x02 /* Series of Object ID numbers, each 4 + bytes long */ + +// +// All internal (opaque) structures are listed here since no one else +// needs to reference them. +// + +// +// The user's Parameter field is mapped out to a structure that contains +// the backlevel 48 WCHARs for Mac/Ras compatibility plus a new structure +// that is basically an array of chars that make up a property name plus +// a property value. +// + +// +// This is the structure for an individual property. Note that there are +// no null terminators in this. +// +typedef struct _USER_PROPERTY { + WCHAR PropertyLength; // length of property name + WCHAR ValueLength; // length of property value + WCHAR PropertyFlag; // type of property (1 = set, 2 = item) + WCHAR Property[1]; // start of property name, followed by value +} USER_PROPERTY, *PUSER_PROPERTY; + +// +// This is the structure that maps the beginning of the user's Parameters +// field. It is only separate so that we can do a sizeof() without including +// the first property, which may or may not be there. +// + +typedef struct _USER_PROPERTIES_HDR { + WCHAR BacklevelParms[48]; // RAS & Mac data stored here. + WCHAR PropertySignature; // signature that we can look for. + WCHAR PropertyCount; // number of properties present. +} USER_PROPERTIES_HDR, *PUSER_PROPERTIES_HDR; + +// +// This structure maps out the whole of the user's Parameters field when +// the user properties structure is present and at least one property is +// defined. +// + +typedef struct _USER_PROPERTIES { + USER_PROPERTIES_HDR Header; + USER_PROPERTY FirstProperty; +} USER_PROPERTIES, *PUSER_PROPERTIES; + +// +// forward references +// + +NTSTATUS +UserPropertyAllocBlock ( + IN PUNICODE_STRING Existing, + IN ULONG DesiredLength, + IN OUT PUNICODE_STRING New + ); + +BOOL +FindUserProperty ( + PUSER_PROPERTIES UserProperties, + LPWSTR Property, + PUSER_PROPERTY *pUserProperty, + USHORT *pCount + ); + +VOID +RemoveUserProperty ( + UNICODE_STRING *puniUserParms, + PUSER_PROPERTY UserProperty, + USHORT Count, + BOOL *Update + ); + +NTSTATUS +SetUserProperty ( + IN LPWSTR UserParms, + IN LPWSTR Property, + IN UNICODE_STRING PropertyValue, + IN WCHAR PropertyFlag, + OUT LPWSTR *pNewUserParms, // memory has to be freed afer use. + OUT BOOL *Update + ) +/* + This function sets a property field in the user's Parameters field. +*/ +{ + NTSTATUS status; + UNICODE_STRING uniUserParms; + UNICODE_STRING uniNewUserParms; + USHORT Count = 0; + USHORT PropertyLength; + USHORT ValueLength; + PUSER_PROPERTIES UserProperties; + PUSER_PROPERTY UserProperty; + LPWSTR PropertyValueString = NULL; + INT i; + UCHAR *pchValue = NULL; + + // Check if parameters are correct. + if (Property == NULL) + { + return( STATUS_INVALID_PARAMETER ); + } + + // Initialize output variables. + *Update = FALSE; + *pNewUserParms = NULL; + + // Converty UserParms to unicode string. + uniUserParms.Buffer = UserParms; + uniUserParms.Length = UserParms? (lstrlenW(UserParms) + 1)* sizeof (WCHAR) + : 0; + uniUserParms.MaximumLength = uniUserParms.Length; + + /** Get the length of the property name **/ + + PropertyLength = lstrlenW( Property ) * sizeof(WCHAR); + + /** Get the length of the property value **/ + ValueLength = PropertyValue.Length; + + if (ValueLength != 0) + { + // Converty property value to asci string so that + // if property value is 0, it can be stored correctly. + + PropertyValueString = (LPWSTR) LocalAlloc (LPTR, (ValueLength+1)*sizeof (WCHAR)); + + pchValue = (UCHAR *) PropertyValue.Buffer; + + // BUGBUG. Since wsprint converts 0x00 to 20 30 (20 is + // space and 30 is 0), sscanf converts 20 30 to 0. If the + // value is uncode string, this convertsion would not + // convert back to original value. So if we want to store + // some value in the UserParms, we have to pass in ansi + // string. + + for (i = 0; i < ValueLength; i++) + { + wsprintfA ((PCHAR)(PropertyValueString+i), "%02x", *(pchValue+i)); + } + + *(PropertyValueString+ValueLength) = 0; + ValueLength = ValueLength * sizeof (WCHAR); + } + + // + // check that user has valid property structure , if not, create one + // + + if (UserParms != NULL) + { + Count = (lstrlenW (UserParms) + 1)* sizeof(WCHAR); + } + + if (Count < sizeof( USER_PROPERTIES)) + { + Count = sizeof( USER_PROPERTIES_HDR ) + sizeof(WCHAR); + } + + if (ValueLength > 0) + { + Count += sizeof( USER_PROPERTY ) + PropertyLength + ValueLength; + } + + if (Count > 0x7FFF) + { + // can't be bigger than 32K of user parms. + return (STATUS_BUFFER_OVERFLOW); + } + + status = UserPropertyAllocBlock( &uniUserParms, + Count, + &uniNewUserParms ); + + if ( !NT_SUCCESS(status) ) + { + return status; + } + + // Make the output pNewUserParms point to uniNewUserPams's buffer + // which is the new UserParms string. + + *pNewUserParms = uniNewUserParms.Buffer; + + UserProperties = (PUSER_PROPERTIES) uniNewUserParms.Buffer; + + if (FindUserProperty (UserProperties, + Property, + &UserProperty, + &Count)) + { + RemoveUserProperty ( &uniNewUserParms, + UserProperty, + Count, + Update); + } + + // + // If the new value of the property is not null, add it. + // + + if (ValueLength > 0) { + + // find the end of the parameters list + + UserProperty = &(UserProperties->FirstProperty); + + for (Count = 1; Count <= UserProperties->Header.PropertyCount; Count++) + { + UserProperty = (PUSER_PROPERTY) + ((LPSTR)((LPSTR) UserProperty + + sizeof(USER_PROPERTY) + // length of entry + UserProperty->PropertyLength + + UserProperty->ValueLength - + sizeof(WCHAR))); // for Property[0] + } + + // + // append it to the end and update length of string + // + + UserProperty->PropertyFlag = (PropertyFlag & NCP_SET) ? + USER_PROPERTY_TYPE_SET : + USER_PROPERTY_TYPE_ITEM; + + UserProperty->PropertyLength = PropertyLength; + UserProperty->ValueLength = ValueLength; + + RtlCopyMemory( &(UserProperty->Property[0]), + Property, + PropertyLength ); + + RtlCopyMemory( &(UserProperty->Property[PropertyLength / sizeof(WCHAR)]), + PropertyValueString, + ValueLength ); + + uniNewUserParms.Length += + sizeof(USER_PROPERTY) + // length of entry + PropertyLength + // length of property name string + ValueLength - // length of value string + sizeof(WCHAR); // account for WCHAR Property[1] + + UserProperties->Header.PropertyCount++; + + *Update = TRUE; + } + + // UserParms is already null terminated. We don't need to set the + // end of UserParms to be NULL since we zero init the buffer already. + + return( status ); +} // SetUserProperty + +#define MAPHEXTODIGIT(x) ( x >= '0' && x <= '9' ? (x-'0') : \ + x >= 'A' && x <= 'F' ? (x-'A'+10) : \ + x >= 'a' && x <= 'f' ? (x-'a'+10) : 0 ) + + +NTSTATUS +QueryUserProperty ( + IN LPWSTR UserParms, + IN LPWSTR PropertyName, + OUT PWCHAR PropertyFlag, + OUT PUNICODE_STRING PropertyValue + ) +/* + This routine returns a user definable property value as it is stored + in the user's Parameters field. Note that the RAS/MAC fields are + stripped before we start processing user properties. +*/ +{ + USHORT PropertyNameLength; + USHORT Count; + PUSER_PROPERTY UserProperty; + WCHAR *Value; + UINT i; + CHAR *PropertyValueString; + CHAR *pchValue; + + // Set PropertyValue->Length to 0 initially. If the property is not found + // it will still be 0 on exit. + + PropertyValue->Length = 0; + PropertyValue->Buffer = NULL; + + PropertyNameLength = lstrlenW(PropertyName) * sizeof(WCHAR); + + // Check if UserParms have the right structure. + + if (FindUserProperty ((PUSER_PROPERTIES) UserParms, + PropertyName, + &UserProperty, + &Count) ) + { + + Value = (LPWSTR)(LPSTR)((LPSTR) &(UserProperty->Property[0]) + + PropertyNameLength); + + // + // Found the requested property + // + + // + // Copy the property flag. + // + + if (PropertyFlag) + *PropertyFlag = UserProperty->PropertyFlag; + + // Allocate memory for PropertyValue->Buffer + + PropertyValueString = LocalAlloc ( LPTR, UserProperty->ValueLength+1); + PropertyValue->Buffer = LocalAlloc ( LPTR, UserProperty->ValueLength/sizeof(WCHAR)); + + // + // Make sure the property value length is valid. + // + if ((PropertyValue->Buffer == NULL) || (PropertyValueString == NULL)) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + // + // Copy the property value to the buffer. + // + + RtlCopyMemory( PropertyValueString, + Value, + UserProperty->ValueLength ); + + pchValue = (CHAR *) PropertyValue->Buffer; + + // Convert from value unicode string to value. + for (i = 0; i < UserProperty->ValueLength/sizeof(WCHAR) ; i++) + { + // sscanf will trash memory. + // sscanf( PropertyValueString+2*i, "%2x", pchValue+i); + + pchValue[i] = MAPHEXTODIGIT( PropertyValueString[2*i]) * 16 + + MAPHEXTODIGIT( PropertyValueString[2*i+1]); + } + + PropertyValue->Length = UserProperty->ValueLength/sizeof(WCHAR); + PropertyValue->MaximumLength = UserProperty->ValueLength/sizeof(WCHAR); + + LocalFree( PropertyValueString); + } + + return STATUS_SUCCESS; +} // QueryUserProperty + + +// Common routine used by QueryUserProperty() and SetUserProperty(). + +BOOL +FindUserProperty ( + PUSER_PROPERTIES UserProperties, + LPWSTR Property, + PUSER_PROPERTY *pUserProperty, + USHORT *pCount + ) +{ + BOOL fFound = FALSE; + USHORT PropertyLength; + + // + // Check if user has valid property structure attached, + // pointed to by UserProperties. + // + + if ( ( UserProperties != NULL ) + && ( lstrlenW( (LPWSTR) UserProperties) * sizeof(WCHAR) > + sizeof(UserProperties->Header.BacklevelParms)) + && ( UserProperties->Header.PropertySignature == USER_PROPERTY_SIGNATURE) + ) + { + // + // user has valid property structure. + // + + *pUserProperty = &(UserProperties->FirstProperty); + + PropertyLength = lstrlenW( Property ) * sizeof(WCHAR); + + for ( *pCount = 1; *pCount <= UserProperties->Header.PropertyCount; + (*pCount)++ ) + { + if ( ( PropertyLength == (*pUserProperty)->PropertyLength ) + && ( RtlCompareMemory( &((*pUserProperty)->Property[0]), + Property, + PropertyLength ) == PropertyLength ) + ) + { + fFound = TRUE; + break; + } + + *pUserProperty = (PUSER_PROPERTY) + ((LPSTR) (*pUserProperty) + + sizeof( USER_PROPERTY ) + + (*pUserProperty)->PropertyLength + + (*pUserProperty)->ValueLength + - sizeof(WCHAR)); // for Property[0] + } + } + + return( fFound ); +} // FindUserProperty + + +// Remove a property field from the User Parms. + +VOID +RemoveUserProperty ( + UNICODE_STRING *puniUserParms, + PUSER_PROPERTY UserProperty, + USHORT Count, + BOOL *Update + ) +{ + PUSER_PROPERTIES UserProperties; + PUSER_PROPERTY NextProperty; + USHORT OldParmLength; + + UserProperties = (PUSER_PROPERTIES) puniUserParms->Buffer; + + OldParmLength = sizeof( USER_PROPERTY ) + + UserProperty->PropertyLength + + UserProperty->ValueLength - + sizeof(WCHAR); // for Property[0] + + + NextProperty = (PUSER_PROPERTY)(LPSTR)((LPSTR) UserProperty + OldParmLength); + + // + // if we're not on the last one, copy the remaining buffer up + // + + if (Count < UserProperties->Header.PropertyCount) { + + RtlMoveMemory( UserProperty, + NextProperty, + puniUserParms->Length - + ((LPSTR) NextProperty - + (LPSTR) puniUserParms->Buffer )); + } + + // + // Now reduce the length of the buffer by the amount we pulled out + // + + puniUserParms->Length -= OldParmLength; + + UserProperties->Header.PropertyCount--; + + *Update = TRUE; +} // RemoveUserProperty + + +NTSTATUS +UserPropertyAllocBlock ( + IN PUNICODE_STRING Existing, + IN ULONG DesiredLength, + IN OUT PUNICODE_STRING New + ) +/* + This allocates a larger block for user's parameters and copies the old + block in. +*/ +{ + PUSER_PROPERTIES UserProperties; + CLONG Count; + WCHAR *pNewBuff; + + + // + // We will allocate a new buffer to store the new parameters + // and copy the existing parameters into it. + // + + New->Buffer = LocalAlloc (LPTR, DesiredLength); + + if ( New->Buffer == NULL) + { + return STATUS_INSUFFICIENT_RESOURCES; + } + + New->MaximumLength = (USHORT) DesiredLength; + + if (Existing != NULL) + { + + New->Length = Existing->Length; + + RtlCopyMemory( New->Buffer, + Existing->Buffer, + Existing->Length ); + } + else + { + New->Length = 0; + } + + // + // Ensure that we don't have any nulls in our string. + // + + for ( Count = 0; + Count < New->Length / sizeof(WCHAR); + Count++ ) + { + if (*(New->Buffer + Count) == L'\0') + { + New->Length = (USHORT) Count * sizeof(WCHAR); + break; + } + } + + // + // now pad it out with spaces until reached Mac+Ras reserved length + // + + pNewBuff = (WCHAR *) New->Buffer + ( New->Length / sizeof(WCHAR) ); + + while ( New->Length < sizeof(UserProperties->Header.BacklevelParms)) + { + *( pNewBuff++ ) = L' '; + New->Length += sizeof(WCHAR); + } + + // + // If the signature isn't there, stick it in and set prop count to 0 + // + + UserProperties = (PUSER_PROPERTIES) New->Buffer; + + if (New->Length < sizeof(USER_PROPERTIES_HDR) || + UserProperties->Header.PropertySignature != USER_PROPERTY_SIGNATURE) + { + + UserProperties->Header.PropertySignature = USER_PROPERTY_SIGNATURE; + UserProperties->Header.PropertyCount = 0; + + New->Length = sizeof(USER_PROPERTIES_HDR); + } + + return STATUS_SUCCESS; +} // UserPropertyAllocBlock + +// usrprop.c eof. |