summaryrefslogtreecommitdiffstats
path: root/private/net/svcdlls/rpl/server/fitfile.c
diff options
context:
space:
mode:
Diffstat (limited to 'private/net/svcdlls/rpl/server/fitfile.c')
-rw-r--r--private/net/svcdlls/rpl/server/fitfile.c442
1 files changed, 442 insertions, 0 deletions
diff --git a/private/net/svcdlls/rpl/server/fitfile.c b/private/net/svcdlls/rpl/server/fitfile.c
new file mode 100644
index 000000000..9aa421920
--- /dev/null
+++ b/private/net/svcdlls/rpl/server/fitfile.c
@@ -0,0 +1,442 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ fitfile.c
+
+Abstract:
+
+ Processes the FIT file referenced in workstation record, eliminating
+ the following keywords:
+
+ (DOSFIT) defines the UNC path of the temporary files used
+ by the new DOS boot (this will probably be removed very soon).
+
+ (CNAME) the netbios cname of the workstation
+
+ (PROFILE) a directory tree for the the shareable config files
+
+ (RPLFILES) share for the configuration and per workstation files
+
+ (SWAPPATH) share for the swap and tmp files, (== (RPLFILES) by default)
+
+ (RPLBINS) share for all executable files, (== (RPLFILES) by default)
+
+ (SRVNAME) the name of RPL server, by default the current netbios name.
+ The server name is usually replaced by the share names.
+
+ The keywords are replaced by the actual parameters. CNAME and PROFILES
+ are defined in the workstation line of RPL.map and the last parameters
+ are optional lanman.ini parameters. (RPLFILES) is by default
+ \\CurrentServer\RPLFILE and (SWAPPATH) and (RPLBINS) are the same share,
+ if they have not been defined in lanman.ini.
+ Procedure supports the tilde replacement (e.g: ~~~~~~~~~~2) similar to
+ the old IBM RIPL. OEMs may define their own tilde fileds in the
+ rpl.map workstation lines, if they really want to. The default system
+ uses the tilde replacement only for per workstation (PROFILE) and (CNAME).
+ The alias keys are first translated to tildes and then they are
+ translated to wksta line fields.
+
+ Also removes all extra comments and spaces from the fit to save DOS and
+ OS/2 memory.
+
+ Provides fitfile functionality similar to that contained in rmapopen.c
+ of LANMAN 2.1 code.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Environment:
+
+ User mode
+
+Revision History :
+
+--*/
+
+#include "local.h"
+#include "fitfile.h"
+
+#define TAB_CHAR L'\t'
+#define LEFT_BRACKET_CHAR L'('
+#define BACK_SLASH_CHAR L'\\'
+
+
+INT RplEatSpaces( IN OUT LPWSTR Source)
+/*++
+
+Routine Description:
+
+ Deletes the extra white space characters in the fit string.
+ Only one white space or tabulator is necessary.
+
+Arguments:
+
+ Source - string to process
+
+Return Value:
+
+ Length in characters of the modified string (not counting the
+ terminating NULL character).
+
+--*/
+{
+ LPWSTR Origin = Source;
+ LPWSTR Target = Source;
+ WCHAR ch;
+
+ for (;;) {
+
+ while ( (ch = *Target++ = *Source++)!=0 && ch!=SPACE_CHAR
+ && ch!=TAB_CHAR) {
+ NOTHING; // copy characters until nul, tab or space character is found
+ }
+
+ if ( ch == 0) {
+ break; // end of string
+ }
+
+ if (ch == TAB_CHAR) {
+ *(Target - 1) = SPACE_CHAR; // replace tab with a space
+ }
+
+ while (*Source == SPACE_CHAR || *Source == TAB_CHAR) {
+ Source++; // skip extra tabs & spaces
+ }
+
+ //
+ // If the next character is a space character (e.g. newline)
+ // then this space is unnecessary, write on it in the next time.
+ //
+ if ( iswspace(*Source)) {
+ Target--;
+ }
+ }
+ return( Target-Origin - 1); // no casts are needed
+
+} // EatSpaces()
+
+
+VOID RplFitAliasInit( IN OUT PRPL_WORKER_DATA pWorkerData)
+/*++
+ Must make sure number of these entries equals FIT_ALIAS_ARRAY_LENGTH
+--*/
+{
+ DWORD Index;
+ PFIT_ALIAS pFitAlias;
+ PFIT_ALIAS FitAliasArray;
+
+ pFitAlias = FitAliasArray = &( pWorkerData->FitAliasArray[0]);
+
+ pFitAlias->Key = L"(PROFILE)"; // profile name of RPL wksta
+ pFitAlias->Value = pWorkerData->ProfileName;
+
+ (++pFitAlias)->Key = L"(CNAME)"; // computer name of RPL wksta
+ pFitAlias->Value = pWorkerData->WkstaName;
+
+//
+// (RPL_SERVER_NAME) is not documented by us nor used in our FIT files.
+// We should probably remove this entry.
+//
+ (++pFitAlias)->Key = L"(RPL_SERVER_NAME)"; // computer name of RPL server
+ pFitAlias->Value = RG_ComputerName;
+
+//
+// (RPLFILES) must be the FIRST SHARE in the array, because it is the
+// default used in (TMPFILES) and (BINFILES) if they are not defined!
+//
+ (++pFitAlias)->Key = L"(RPLFILES)";
+ pFitAlias->Value = RG_UncRplfiles;
+
+ (++pFitAlias)->Key = L"(TMPFILES)";
+ pFitAlias->Value = L"TMPFILES";
+
+ (++pFitAlias)->Key = L"(BINFILES)";
+ pFitAlias->Value = L"BINFILES";
+
+//
+// (COMPUTER_NAME) is not documented by us nor used in our FIT files.
+// It has the same purpose as (CNAME) and was kept for compatibility
+// with some old NOKIA FIT files. We should probably remove this entry.
+//
+ (++pFitAlias)->Key = L"(COMPUTER_NAME)";
+ pFitAlias->Value = RG_ComputerName;
+
+ RPL_ASSERT( FitAliasArray + FIT_ALIAS_ARRAY_LENGTH == ++pFitAlias);
+
+ for ( Index = 0; Index < FIT_ALIAS_ARRAY_LENGTH; Index++) {
+ FitAliasArray[ Index].KeyLength = wcslen( FitAliasArray[ Index].Key);
+ FitAliasArray[ Index].ValueLength = wcslen( FitAliasArray[ Index].Value);
+ }
+}
+
+
+PFIT_ALIAS RplFitFind( IN PFIT_ALIAS FitAliasArray, IN LPWSTR Key)
+/*++
+
+Routine Description:
+ Looks for FIT_ALIAS containing input key string.
+
+Arguments:
+ Key - ptr to key string
+
+Return Value:
+ Returns the pointer of a FIT alias structure or NULL if the the key was not found.
+
+--*/
+{
+ DWORD index;
+
+ for ( index = 0; index < FIT_ALIAS_ARRAY_LENGTH; index++) {
+ if ( !wcsncmp( FitAliasArray[ index].Key, Key, FitAliasArray[ index].KeyLength)) {
+ return &(FitAliasArray[ index]);
+ }
+ }
+ return( NULL);
+}
+
+
+DWORD RplFitNewLength( IN LPWSTR pFitImage, IN PFIT_ALIAS FitAliasArray)
+{
+ PWCHAR Cursor;
+ PFIT_ALIAS pFitAlias;
+ INT Length;
+
+ //
+ // Calculate the length of the new fit file. Some key replacements
+ // will increase the total length, the other decrease it.
+ //
+ for ( Cursor = pFitImage, Length = wcslen( pFitImage);
+ ( Cursor = wcschr( Cursor, LEFT_BRACKET_CHAR)) != NULL;
+ Cursor++) {
+
+ if ( (pFitAlias = RplFitFind( FitAliasArray, Cursor)) != NULL) {
+ //
+ // We found a keyword, replacement should be made, see how this
+ // would change the total length of FIT data.
+ //
+ Length += (INT)pFitAlias->ValueLength - (INT)pFitAlias->KeyLength;
+ }
+ }
+ return( Length);
+}
+
+
+VOID RplFitReplaceKeys(
+ OUT PWCHAR Target,
+ IN PWCHAR Source,
+ IN PFIT_ALIAS FitAliasArray
+ )
+/*++
+ Replace keywords.
+
+--*/
+{
+ PFIT_ALIAS pFitAlias;
+ PWCHAR Cursor;
+ INT Length;
+
+ Cursor = Source; // Initailize
+
+ while ( (Cursor = wcschr( Cursor, LEFT_BRACKET_CHAR)) != NULL) {
+
+ if ( (pFitAlias = RplFitFind( FitAliasArray, Cursor)) != NULL) {
+ //
+ // Copy stuff before the keyword, then copy the replacement string.
+ //
+ Length = Cursor - Source; // no casts are needed
+ memcpy( Target, Source, Length * sizeof( WCHAR));
+ memcpy( Target + Length, pFitAlias->Value, pFitAlias->ValueLength * sizeof( WCHAR));
+ Source += Length + pFitAlias->KeyLength;
+ Target += Length + pFitAlias->ValueLength;
+ Cursor += pFitAlias->KeyLength; // skip entire key
+ } else {
+ Cursor++; // skip LEFT_BRACKET_CHAR
+ }
+ }
+ //
+ // Here LEFT_BRACKET is NULL and we still need to copy from Source to the end of the
+ // string, including the terminal zero.
+ //
+ wcscpy( Target, Source);
+}
+
+
+VOID RplStripComments( IN OUT LPWSTR buffer)
+/*++
+
+Routine Description:
+ Skips leading spaces in each line and removes all comments lines
+ from a buffer containing FIT file.
+
+Arguments:
+ buffer - pointer to buffer containing FIT file, the buffer is NULL
+ terminated.
+
+Return Value:
+ None.
+
+--*/
+{
+ PWCHAR Cursor; // running cursor
+ PWCHAR LineEnd; // pointer to NEW_LINE_CHAR
+
+ Cursor = buffer;
+ for ( ; ;) {
+ //
+ // We are at the beginning of a line, skip leading white space characters.
+ //
+ Cursor += wcsspn( Cursor, L" \f\n\r\t\v");
+ if ( *Cursor == 0) {
+ break; // we reached the end of a string
+ }
+
+ LineEnd = wcschr( Cursor, NEW_LINE_CHAR);
+ if ( LineEnd == NULL) {
+ break; // ignore stuff without end of line
+ }
+ LineEnd++; // make it point beyond NEW_LINE_CHAR we just found
+
+ //
+ // Copy only the non comment lines. Memmove below works even
+ // for overlapping memory regions.
+ //
+ if ( *Cursor != COMMENT_CHAR) {
+ INT Length = LineEnd - Cursor;
+ buffer = (PWCHAR)memmove( buffer, Cursor, Length * sizeof(WCHAR)) + Length;
+ }
+ Cursor = LineEnd;
+ }
+ *buffer = 0; // null terminate
+}
+
+
+
+VOID RplFitStripRplfiles( IN OUT LPWSTR Buffer)
+/*++
+ The first line in a FIT file is a special case, it must contain the
+ default UNC share used in a FIT file. This UNC name need not be
+ anywhere else in a FIT file, so remove all other references.
+
+ BUGBUG: should we insist FIT file contains UNC name in the first line ??
+
+--*/
+{
+ PWCHAR Cursor;
+ INT Length;
+
+ if ( Buffer[0] == BACK_SLASH_CHAR && Buffer[1] == BACK_SLASH_CHAR) {
+ //
+ // First line contains UNC name, remember its length.
+ //
+ Cursor = wcspbrk( Buffer, L" \f\n\r\t\v");
+ Length = Cursor - Buffer; // no casts are needed
+
+ while ( (Cursor = wcsstr( Cursor, DOUBLE_BACK_SLASH_STRING)) != NULL) {
+ if ( !wcsncmp( Buffer, Cursor, Length) && Cursor[ Length] == BACK_SLASH_CHAR) {
+ memset( Cursor, SPACE_CHAR, (Length + 1) * sizeof( WCHAR));
+ Cursor += Length + 1;
+ } else {
+ Cursor += (sizeof(DOUBLE_BACK_SLASH_STRING)/sizeof(WCHAR) - 1);
+ }
+ }
+ }
+}
+
+
+BOOL RplFitFile( IN OUT PRPL_WORKER_DATA pWorkerData)
+{
+ PFIT_ALIAS FitAliasArray;
+ LPWSTR UnicodeString; // UNICODE content of FIT file
+ PWCHAR Target;
+ INT UnicodeStringLength;
+ BOOL Success;
+
+ RplDump( RG_DebugLevel & RPL_DEBUG_FLOW,( "++FitFile"));
+
+ Success = FALSE;
+ FitAliasArray = &( pWorkerData->FitAliasArray[ 0]);
+
+ //
+ // Initalize FIT_ALIAS[] array since it will be used in calculations below.
+ //
+ RplFitAliasInit( pWorkerData);
+
+ //
+ // Read FIT file data as a UNICODE string.
+ //
+ UnicodeString = RplReadTextFile( pWorkerData->MemoryHandle,
+ pWorkerData->FitFile, MAX_FIT_FILE_SIZE);
+ if ( UnicodeString == NULL) {
+ RplDump( ++RG_Assert, ( "FitFile=%ws", pWorkerData->FitFile));
+ pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
+ pWorkerData->EventStrings[ 1] = pWorkerData->FitFile;
+ pWorkerData->EventId = NELOG_RplWkstaFileRead;
+ return( FALSE);
+ }
+
+ //
+ // Remove the comments and all unnecessary spaces. There should be not
+ // extra characters in FIT, because they eat both DOS and OS/2 memory.
+ //
+ RplStripComments( UnicodeString);
+
+ //
+ // Calculate space needed for a UNICODE version of FIT file after we make
+ // all key replacements.
+ //
+ UnicodeStringLength = RplFitNewLength( UnicodeString, FitAliasArray);
+
+ //
+ // Allocate space for UNICODE version of FIT file.
+ //
+ Target = RplMemAlloc( pWorkerData->MemoryHandle, (UnicodeStringLength+1) * sizeof( WCHAR));
+ if ( Target == NULL) {
+ pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
+ pWorkerData->EventId = NELOG_RplWkstaMemory;
+ goto cleanup;
+ }
+
+ RplFitReplaceKeys( Target, UnicodeString, FitAliasArray);
+ RplMemFree( pWorkerData->MemoryHandle, UnicodeString);
+ UnicodeString = Target;
+
+ //
+ // Get rid of RPLFILES duplicates.
+ //
+ RplFitStripRplfiles( UnicodeString);
+
+ UnicodeStringLength = RplEatSpaces( UnicodeString); // compactify
+ _wcsupr( UnicodeString); // upppercase
+
+ //
+ // Convert UNICODE fit string into DBCS fit string.
+ //
+ pWorkerData->ClientFitSize = RplUnicodeToDbcs(
+ pWorkerData->MemoryHandle,
+ UnicodeString,
+ UnicodeStringLength,
+ MAX_FIT_FILE_SIZE,
+ &(pWorkerData->ClientFit)
+ );
+ if ( pWorkerData->ClientFitSize == 0) {
+ RplDump( ++RG_Assert, ( "UnicodeString=0x%x, UnicodeString=%ws",
+ UnicodeString, UnicodeString));
+ pWorkerData->EventStrings[ 0] = pWorkerData->WkstaName;
+ pWorkerData->EventStrings[ 1] = pWorkerData->FitFile;
+ pWorkerData->EventId = NELOG_RplWkstaFileSize;
+ goto cleanup;
+ }
+
+ Success = TRUE;
+
+cleanup:
+ if ( UnicodeString != NULL) {
+ RplMemFree( pWorkerData->MemoryHandle, UnicodeString);
+ }
+ RplDump( RG_DebugLevel & RPL_DEBUG_FLOW,( "--FitFile"));
+ return( Success);
+}