summaryrefslogtreecommitdiffstats
path: root/private/net/svcdlls/rpl/convert
diff options
context:
space:
mode:
Diffstat (limited to 'private/net/svcdlls/rpl/convert')
-rw-r--r--private/net/svcdlls/rpl/convert/adapter.c71
-rw-r--r--private/net/svcdlls/rpl/convert/boot.c306
-rw-r--r--private/net/svcdlls/rpl/convert/config.c527
-rw-r--r--private/net/svcdlls/rpl/convert/convert.rc12
-rw-r--r--private/net/svcdlls/rpl/convert/debug.c76
-rw-r--r--private/net/svcdlls/rpl/convert/library.c330
-rw-r--r--private/net/svcdlls/rpl/convert/local.h227
-rw-r--r--private/net/svcdlls/rpl/convert/makefile6
-rw-r--r--private/net/svcdlls/rpl/convert/makefile.inc4
-rw-r--r--private/net/svcdlls/rpl/convert/nlstxt.mc214
-rw-r--r--private/net/svcdlls/rpl/convert/profile.c270
-rw-r--r--private/net/svcdlls/rpl/convert/rpldata.h47
-rw-r--r--private/net/svcdlls/rpl/convert/rplmain.c740
-rw-r--r--private/net/svcdlls/rpl/convert/sources51
-rw-r--r--private/net/svcdlls/rpl/convert/vendor.c139
-rw-r--r--private/net/svcdlls/rpl/convert/wksta.c565
16 files changed, 3585 insertions, 0 deletions
diff --git a/private/net/svcdlls/rpl/convert/adapter.c b/private/net/svcdlls/rpl/convert/adapter.c
new file mode 100644
index 000000000..738dbb67c
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/adapter.c
@@ -0,0 +1,71 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ adapter.c
+
+Abstract:
+
+ Creates adapter table to be used with NT rpl service.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Revision History:
+
+--*/
+
+#include "local.h"
+#define RPLADAPTER_ALLOCATE
+#include "adapter.h"
+#undef RPLADAPTER_ALLOCATE
+
+
+DWORD AdapterCreateTable( VOID)
+{
+ JET_COLUMNDEF ColumnDef;
+ JET_ERR JetError;
+ DWORD index;
+ DWORD Offset;
+ CHAR IndexKey[ 255];
+
+ JetError = JetCreateTable( SesId, DbId, ADAPTER_TABLE_NAME,
+ ADAPTER_TABLE_PAGE_COUNT, ADAPTER_TABLE_DENSITY, &AdapterTableId);
+
+ //
+ // Create columns. First initalize fields that do not change between
+ // addition of columns.
+ //
+ ColumnDef.cbStruct = sizeof(ColumnDef);
+ ColumnDef.columnid = 0;
+ ColumnDef.wCountry = 1;
+ ColumnDef.langid = 0x0409; // USA english
+ ColumnDef.cp = 1200; // UNICODE codepage
+ ColumnDef.wCollate = 0;
+ ColumnDef.cbMax = 0;
+ ColumnDef.grbit = 0; // variable length binary and text data.
+
+ for ( index = 0; index < ADAPTER_TABLE_LENGTH; index++) {
+
+ ColumnDef.coltyp = AdapterTable[ index].ColumnType;
+
+ CallM( JetAddColumn( SesId, AdapterTableId,
+ AdapterTable[ index].ColumnName, &ColumnDef,
+ NULL, 0, &AdapterTable[ index].ColumnId));
+ }
+
+ Offset = AddKey( IndexKey, '+', AdapterTable[ ADAPTER_AdapterName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, AdapterTableId, ADAPTER_INDEX_AdapterName,
+ JET_bitIndexPrimary, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ return( ERROR_SUCCESS);
+}
+
diff --git a/private/net/svcdlls/rpl/convert/boot.c b/private/net/svcdlls/rpl/convert/boot.c
new file mode 100644
index 000000000..e0dacb4ec
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/boot.c
@@ -0,0 +1,306 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ boot.c
+
+Abstract:
+
+ Creates boot block table (server record table). Parses old style
+ RPL.MAP server records and creates corresponding entries in jet
+ database table.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Revision History:
+
+--*/
+
+#include "local.h"
+#define RPLBOOT_ALLOCATE
+#include "boot.h"
+#undef RPLBOOT_ALLOCATE
+
+
+DWORD BootCreateTable( VOID)
+{
+ JET_COLUMNDEF ColumnDef;
+ JET_ERR JetError;
+ DWORD index;
+ DWORD Offset;
+ CHAR IndexKey[ 255];
+
+ JetError = JetCreateTable( SesId, DbId, BOOT_TABLE_NAME,
+ BOOT_TABLE_PAGE_COUNT, BOOT_TABLE_DENSITY, &BootTableId);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateTable failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // Create columns. First initalize fields that do not change between
+ // addition of columns.
+ //
+ ColumnDef.cbStruct = sizeof(ColumnDef);
+ ColumnDef.columnid = 0;
+ ColumnDef.wCountry = 1;
+ ColumnDef.langid = 0x0409; // USA english
+ ColumnDef.cp = 1200; // UNICODE codepage
+ ColumnDef.wCollate = 0;
+ ColumnDef.cbMax = 0;
+ ColumnDef.grbit = 0; // variable length binary and text data.
+
+ for ( index = 0; index < BOOT_TABLE_LENGTH; index++ ) {
+
+ ColumnDef.coltyp = BootTable[ index].ColumnType;
+
+ JetError = JetAddColumn( SesId, BootTableId,
+ BootTable[ index].ColumnName, &ColumnDef,
+ NULL, 0, &BootTable[ index].ColumnId);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("AddColumn( %s) failed err=%d", BootTable[ index].ColumnName, JetError));
+ return( MapJetError( JetError));
+ }
+ }
+
+ //
+ // Boot names of DOS boot blocks may be shared by several adapter id
+ // classes (vendor codes). Therefore, server name (== boot name)
+ // cannot be a unique index nor a primary index. But you can construct
+ // a primary index from VendorId & BootName.
+ // +VendorId+BootName index is used to enumerate all boot names for a
+ // given vendor id - which is then used to enumerate all profiles & all
+ // configs compatible with a given vendor id.
+ //
+ Offset = AddKey( IndexKey, '+', BootTable[ BOOT_VendorId].ColumnName);
+ Offset += AddKey( IndexKey + Offset, '+', BootTable[ BOOT_BootName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, BootTableId, BOOT_INDEX_VendorIdBootName,
+ JET_bitIndexPrimary, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ Offset = AddKey( IndexKey, '+', BootTable[ BOOT_BootName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, BootTableId, BOOT_INDEX_BootName,
+ 0, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // Make boot name a current index - used to validate configs.
+ //
+ JetError = JetSetCurrentIndex( SesId, BootTableId, BOOT_INDEX_BootName);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("SetCurrentIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ return( ERROR_SUCCESS);
+}
+
+
+VOID ProcessBoot( PWCHAR * Fields)
+{
+//
+// Boot block record (server record) defines.
+//
+#define BOOT_BBCFILE_INDEX 1 // boot block configuration file
+#define BOOT_RETRYCOUNT_INDEX 2 // retry count (used with default boot)
+#define BOOT_TIMEOUT_INDEX 3 // retry period (used with default boot)
+#define BOOT_ACKSTATUS_INDEX 4 // used with acknowledgments
+#define BOOT_COMMENT_INDEX 6 // boot block comment
+#define BOOT_VENDOR_INDEX 7 // common adapter id digits
+#define BOOT_BOOTNAME_INDEX 13 // boot block identifier
+
+#define BOOT_DEFAULT_RETRYCOUNT 3
+#define BOOT_DEFAULT_TIMEOUT 10
+#define USE_ACK_CHAR L'A'
+#define FINAL_ACK_ONLY_CHAR L'F'
+#define PARTIAL_ACK_CHAR L'P'
+#define NO_ACK_CHAR L'N'
+#define ADAPT_WIN_CHAR L'W'
+
+ PWCHAR VendorName; // common adapter id digits
+ DWORD VendorId; // common adapter id digits
+ PWCHAR BootName; // id of boot block record
+ PWCHAR BootComment;
+ PWCHAR BbcFile; // boot block configuration file relative path
+#ifdef RPL_OBSOLETE
+ DWORD RetryCount;
+ DWORD RetryPeriod;
+#endif
+ DWORD WindowSize; // used with acknowledgments
+ //
+ // SendFileRequest is of type JET_coltypBit, which is of UCHAR size.
+ // Thus it is declared as BOOLEAN == UCHAR, instead of BOOL == int.
+ //
+ BOOLEAN FinalAck; // used with acknowledgments
+ DWORD Flags;
+
+#ifdef RPL_OBSOLETE
+ //
+ // Initialize retry count & retry period (else use defaults).
+ //
+ if ( iswdigit( *Fields[ BOOT_TIMEOUT_INDEX]) &&
+ iswdigit( *Fields[ BOOT_RETRYCOUNT_INDEX])) {
+ RetryPeriod = wcstoul( Fields[ BOOT_TIMEOUT_INDEX], NULL, 0);
+ RetryCount = wcstoul( Fields[ BOOT_RETRYCOUNT_INDEX], NULL, 0);
+ } else {
+ RetryPeriod = BOOT_DEFAULT_TIMEOUT;
+ RetryCount = BOOT_DEFAULT_RETRYCOUNT;
+ }
+#endif
+
+ switch( toupper( *Fields[ BOOT_ACKSTATUS_INDEX])) {
+ case FINAL_ACK_ONLY_CHAR:
+ WindowSize = MAXWORD; // don't ack any (non-final) packet
+ FinalAck = TRUE; // ack the final packet
+ break;
+ case PARTIAL_ACK_CHAR:
+ WindowSize = 0; // ack every (non-final) packet
+ FinalAck = FALSE; // don't ack the final packet
+ break;
+ case ADAPT_WIN_CHAR:
+ if ( Fields[ BOOT_ACKSTATUS_INDEX][ 1] != EQUALS_CHAR) {
+ WindowSize = 0; // the default is to ack every (non-final) packet
+ } else {
+ WindowSize = wcstoul( Fields[BOOT_ACKSTATUS_INDEX] + 2, NULL, 0);
+ //
+ // Algorithm adds an extra packet to window, decrement counter
+ // by one. (Thus window size of 1 is same as USE_ACK_CHAR.)
+ //
+ if ( WindowSize) { // avoid underflow
+ WindowSize--;
+ }
+ } // ack every WindowSize-th (non-final) packet
+ FinalAck = TRUE; // ack the final packet
+ break;
+ case NO_ACK_CHAR:
+ case 0:
+ WindowSize = MAXWORD; // don't ack any (non-final) packet
+ FinalAck = FALSE; // don't ack the final packet
+ break;
+ default:
+ DbgUserBreakPoint();
+ NOTHING; // fall through to most common case
+ case USE_ACK_CHAR:
+ WindowSize = 0; // ack every (non-final) packet
+ FinalAck = TRUE; // ack the final packet
+ break;
+ }
+ WindowSize = 0; // BUGBUG temporary workaround for RPLSVC bug
+
+ if ( FinalAck == TRUE) {
+ Flags = BOOT_FLAGS_FINAL_ACKNOWLEDGMENT_TRUE;
+ } else {
+ Flags = BOOT_FLAGS_FINAL_ACKNOWLEDGMENT_FALSE;
+ }
+
+ BootComment = Fields[ BOOT_COMMENT_INDEX];
+ if ( RPL_STRING_TOO_LONG( BootComment)) {
+ BootComment[ RPL_MAX_STRING_LENGTH] = 0; // silently truncate it
+ }
+
+
+ //
+ // Note that server identifier has leading 'R' (enabled) or 'D'
+ // (disabled) in wksta record but it always has leading 'R' in server
+ // record. We do not want to save leading 'R' in server record.
+ //
+ BootName = Fields[ BOOT_BOOTNAME_INDEX] + 1; // add 1 to skip leading 'R'
+ if ( !ValidName( BootName, RPL_MAX_BOOT_NAME_LENGTH, TRUE)) {
+ RplPrintf1( RPLI_CVT_BootNameTooLong, BootName);
+ return;
+ }
+
+ BbcFile = Fields[ BOOT_BBCFILE_INDEX];
+ if ( !ValidName( BbcFile, RPL_MAX_STRING_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_BbcFileTooLong, BootName, BbcFile);
+ return;
+ }
+
+ //
+ // LM2.2 introduced multiple vendor codes in the vendor field of a
+ // boot block record. For each of the vendor codes we create a
+ // separate jet record.
+ //
+ // Store common adapter id digits both as a hex string (VendorName)
+ // and as a dword (VendorId).
+ //
+ for ( VendorName = wcstok( Fields[ BOOT_VENDOR_INDEX], L"|");
+ VendorName != NULL; VendorName = wcstok( NULL, L"|")) {
+
+ if ( !ValidHexName( VendorName, RPL_VENDOR_NAME_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_BadVendorName, BootName, VendorName);
+ continue;
+ }
+
+ VendorId = wcstoul( VendorName, NULL, 16); // since VendorName must be hex
+
+ Call( JetPrepareUpdate( SesId, BootTableId, JET_prepInsert));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_BootName].ColumnId,
+ BootName, (wcslen( BootName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_BootComment].ColumnId,
+ BootComment, (wcslen( BootComment) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_Flags].ColumnId,
+ &Flags, sizeof( Flags), 0, NULL));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_VendorName].ColumnId,
+ VendorName, (wcslen( VendorName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_BbcFile].ColumnId,
+ BbcFile, (wcslen( BbcFile) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_WindowSize].ColumnId,
+ &WindowSize, sizeof( WindowSize), 0, NULL));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_VendorId].ColumnId,
+ &VendorId, sizeof( VendorId), 0, NULL));
+
+#ifdef RPL_OBSOLETE
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_RetryCount].ColumnId,
+ &RetryCount, sizeof( RetryCount), 0, NULL));
+
+ Call( JetSetColumn( SesId, BootTableId,
+ BootTable[ BOOT_RetryPeriod].ColumnId,
+ &RetryPeriod, sizeof( RetryPeriod), 0, NULL));
+#endif
+
+ Call( JetUpdate( SesId, BootTableId, NULL, 0, NULL));
+ }
+}
+
+
+BOOL FindBoot( IN PWCHAR BootName)
+{
+ return( Find( BootTableId, BootName));
+}
+
+
+VOID BootListTable( VOID)
+{
+ ListTable( BOOT_TABLE_NAME, BootTable[ BOOT_BootName].ColumnName,
+ BOOT_INDEX_BootName);
+}
+
+
diff --git a/private/net/svcdlls/rpl/convert/config.c b/private/net/svcdlls/rpl/convert/config.c
new file mode 100644
index 000000000..99215c4f5
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/config.c
@@ -0,0 +1,527 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ config.c
+
+Abstract:
+
+ Creates config table. Parses old style RPLMGR.INI config records
+ and creates corresponding entries in jet database table.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Revision History:
+
+--*/
+
+#include "local.h"
+#define RPLCONFIG_ALLOCATE
+#include "config.h"
+#undef RPLCONFIG_ALLOCATE
+
+PWCHAR RplmgrIniFile = L"rplmgr.ini";
+
+#define MAX_RPLMGR_INI_FILE_SIZE 0xFFFF // BUGBUG some arbitrary value
+
+#define NO_SCRIPT_FIELDS 13
+
+#define SECTION_STARTMARK L'['
+#define CONFIG_BEGIN L"[configuration]"
+
+#define CARRIAGE_RETURN_CHAR L'\r' // 0xD or \015
+
+// #define RPL_DEBUG_ALL
+
+
+BOOL GetConfigFieldValue(
+ IN PWCHAR Cursor,
+ IN DWORD Index
+ )
+/*++
+ Fields with multiple field values, such as AdapterName, are
+ not properly parsed here. Howerever, we do not care about
+ the values of these fields.
+--*/
+{
+ PWCHAR End;
+ DWORD Length;
+
+ //
+ // By default the field is empty.
+ //
+ ConfigParseTable[ Index].Value = NULL;
+ ConfigParseTable[ Index].Size = 0;
+
+ //
+ // Read to EQUALS_CHAR
+ //
+ while ( *Cursor != EQUALS_CHAR && *Cursor != COMMENT_CHAR &&
+ *Cursor != CARRIAGE_RETURN_CHAR) {
+ Cursor++;
+ }
+
+ if ( *Cursor == COMMENT_CHAR || *Cursor == CARRIAGE_RETURN_CHAR) {
+ return( TRUE);
+ }
+
+ Cursor++; // Skip EQUALS_CHAR
+
+ //
+ // Read to the beginning of field value.
+ //
+ while( *Cursor != CARRIAGE_RETURN_CHAR && iswspace(*Cursor) &&
+ *Cursor != COMMENT_CHAR) {
+ Cursor++;
+ }
+
+ if ( *Cursor == COMMENT_CHAR || *Cursor == CARRIAGE_RETURN_CHAR) {
+ return( TRUE);
+ }
+
+ //
+ // Make sure that boot block reference is enabled.
+ //
+ if ( Index == CONFIG_BootName) {
+ if ( *Cursor != L'R') {
+ RplAssert( TRUE, ("Bad boot block id: %.40ws", Cursor));
+ return( FALSE);
+ }
+ Cursor++; // skip leading 'R' in boot block name
+ }
+
+ //
+ // Find the end point of this field. Since comments may contain spaces,
+ // space is not used as a separator for CONFIG_ConfigComment field.
+ //
+
+ End = wcspbrk( Cursor, Index == CONFIG_ConfigComment ? L"\f\n\r\t\v" : L" \f\n\r\t\v");
+ if ( End != NULL) {
+ Length = End - Cursor;
+ } else {
+ Length = wcslen( Cursor);
+ }
+
+ ConfigParseTable[ Index].Value = GlobalAlloc( GMEM_FIXED, (Length+1)*sizeof(WCHAR));
+ if ( ConfigParseTable[ Index].Value == NULL) {
+ DWORD Error = GetLastError();
+ RplAssert( TRUE, ("GlobalAlloc: Error = %d", Error));
+ return( FALSE);
+ }
+ ConfigParseTable[ Index].Size = (Length+1)*sizeof(WCHAR);
+ memcpy( ConfigParseTable[ Index].Value, Cursor, Length * sizeof(WCHAR));
+ ((PWCHAR)ConfigParseTable[ Index].Value)[ Length] = 0;
+ return( TRUE);
+}
+
+
+BOOL StringISpaceEqual( IN PWCHAR str1, IN PWCHAR str2 )
+/*++
+
+Routine Description:
+
+ Case insensitive version of StringsSpaceEqual.
+
+Arguments:
+
+ str1 - first string
+ str2 - second string
+
+Return Value:
+
+ TRUE if strings are equal, FALSE otherwise.
+
+--*/
+{
+ WCHAR ch1;
+
+#ifdef NOT_YET
+ if ( str1 == NULL || str2 == NULL) {
+ str1 = (str1 != NULL) ? str1 : str2;
+ if ( str2 == NULL) {
+ return( TRUE); // both strings are NULL
+ }
+ while ( iswspace( *str1++)) {
+ NOTHING; // check if not NULL string contains spaces only
+ }
+ return( *str1 == 0);
+ }
+#endif // NOT_YET
+
+ //
+ // Compare strings until the first space or NULL character
+ // (in the first string) or until we find the first different character.
+ //
+ while ( (ch1 = toupper(*str1)) && !iswspace(ch1) && ch1 == toupper(*str2)) {
+ str1++, str2++;
+ }
+
+ //
+ // For strings to be equal, both characters must be NULL or space.
+ //
+ if ( (!ch1 || iswspace(ch1)) && (!(ch1 = *str2) || iswspace(ch1)))
+ {
+ return( TRUE);
+ }
+
+ return( FALSE);
+}
+
+
+#ifdef RPL_DEBUG_ALL
+VOID ProcessConfigDisplay( VOID)
+{
+ DWORD Index;
+
+ printf( "\tCONFIGURATION\n");
+ for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++) {
+ if ( ConfigParseTable[ Index].Name == NULL) {
+ continue;
+ }
+ printf( "%ws %ws 0x%x\n", ConfigParseTable[ Index].Name,
+ ConfigParseTable[ Index].Value, ConfigParseTable[ Index].Size);
+ }
+}
+#endif
+
+
+PWCHAR ProcessConfig( IN PWCHAR Cursor)
+/*++
+
+Routine Description:
+
+ We read all the fields in the Config[] array, then use jet apis
+ to store this config in the database.
+
+Arguments:
+
+ Cursor - at entry this points to the beginning of the config section
+
+Return Value:
+
+ Cursor value after we finished processing the current config section.
+
+--*/
+{
+#define INVALID_ERROR_PARAMETER ((DWORD)(-1))
+ DWORD Index;
+ JET_ERR JetError;
+ DWORD Flags;
+ DWORD Offset;
+ DWORD ErrorParameter;
+
+ for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++) {
+ if ( ConfigParseTable[ Index].Value != NULL) {
+ GlobalFree( ConfigParseTable[ Index].Value);
+ }
+ ConfigParseTable[ Index].Value = NULL;
+ }
+ if ( OffsetAfterComment( Cursor) == 0) {
+ Flags = CONFIG_FLAGS_ENABLED_TRUE;
+ } else {
+ Flags = CONFIG_FLAGS_ENABLED_FALSE;
+ }
+
+ for ( Cursor=GetNextLine(Cursor), ErrorParameter = INVALID_ERROR_PARAMETER;
+ *Cursor!=0; Cursor=GetNextLine(Cursor)) {
+
+ Offset = OffsetAfterComment( Cursor);
+ if ( *(Cursor+Offset) == SECTION_STARTMARK) {
+ break; // start of a new section, write the current section
+ }
+ Cursor += Offset;
+
+ //
+ // Find value for this name.
+ //
+ for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++) {
+ if ( ConfigParseTable[ Index].Name == NULL) {
+ continue; // skip this one, not a RPLMGR.INI keyword
+ }
+ if ( !StringISpaceEqual( Cursor, ConfigParseTable[ Index].Name)) {
+ continue; // no match with this keyword
+ }
+ if ( !GetConfigFieldValue( Cursor, Index)) {
+ if ( ErrorParameter == INVALID_ERROR_PARAMETER) {
+ ErrorParameter = Index;
+ }
+ } else if ( Index == CONFIG_FitShared || Index == CONFIG_FitPersonal) {
+ PWCHAR Value;
+ Value = AddFileExtension( ConfigParseTable[ Index].Value,
+ L".FIT", TRUE);
+ if ( Value == NULL) {
+ if ( ErrorParameter == INVALID_ERROR_PARAMETER) {
+ ErrorParameter = Index;
+ }
+ } else if ( Value != ConfigParseTable[ Index].Value) {
+ GlobalFree( ConfigParseTable[ Index].Value);
+ ConfigParseTable[ Index].Value = Value;
+ ConfigParseTable[ Index].Size = (wcslen(Value)+1)*sizeof(WCHAR);
+ }
+ }
+ break;
+ }
+ }
+#ifdef RPL_DEBUG_ALL
+ ProcessConfigDisplay();
+#endif
+
+ if ( ConfigParseTable[ CONFIG_ConfigName].Value == NULL) {
+ RplAssert( TRUE, ("Bad config"));
+ return( Cursor);
+ }
+
+ //
+ // Perform same checks as in NetrRplConfigAdd.
+ //
+ if ( ErrorParameter != INVALID_ERROR_PARAMETER) {
+ NOTHING; // do not overwrite the first error
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_FitPersonal].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
+ ErrorParameter = CONFIG_FitPersonal;
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_FitShared].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
+ ErrorParameter = CONFIG_FitShared;
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_DirName4].Value, RPL_MAX_STRING_LENGTH, FALSE)) {
+ ErrorParameter = CONFIG_DirName4;
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_DirName3].Value, RPL_MAX_STRING_LENGTH, FALSE)) {
+ ErrorParameter = CONFIG_DirName3;
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_DirName2].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
+ ErrorParameter = CONFIG_DirName2;
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_DirName].Value, RPL_MAX_STRING_LENGTH, TRUE)) {
+ ErrorParameter = CONFIG_DirName;
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_BootName].Value, RPL_MAX_BOOT_NAME_LENGTH, TRUE)) {
+ ErrorParameter = CONFIG_BootName;
+ } else if ( !ValidName( ConfigParseTable[ CONFIG_ConfigName].Value, RPL_MAX_CONFIG_NAME_LENGTH, TRUE)) {
+ ErrorParameter = CONFIG_ConfigName;
+ }
+
+ if ( ErrorParameter < CONFIG_TABLE_LENGTH) {
+ RplPrintf2( RPLI_CVT_ConfigInvalid, ConfigParseTable[ CONFIG_ConfigName].Value, ConfigParseTable[ ErrorParameter].Name);
+ return( Cursor);
+ }
+
+ if ( ConfigParseTable[ CONFIG_FitPersonal].Value == NULL) {
+ //
+ // Ignore default boot configurations.
+ //
+ RplPrintf1( RPLI_CVT_ConfigNoPersonalFIT, ConfigParseTable[ CONFIG_ConfigName].Value);
+ return( Cursor);
+ }
+
+ if ( !_wcsicmp( L"OS2", ConfigParseTable[ CONFIG_DirName].Value )) {
+ //
+ // Ignore OS/2 configurations.
+ //
+ RplPrintf1( RPLI_CVT_ConfigNoOS2, ConfigParseTable[ CONFIG_ConfigName].Value);
+ return( Cursor);
+ }
+
+ if ( RPL_STRING_TOO_LONG( ConfigParseTable[ CONFIG_ConfigComment].Value)) {
+ //
+ // Silently truncate comments that are too long.
+ //
+ ((PWCHAR)ConfigParseTable[ CONFIG_ConfigComment].Value)[ RPL_MAX_STRING_LENGTH] = 0;
+ ConfigParseTable[ CONFIG_ConfigComment].Size = (RPL_MAX_STRING_LENGTH+1)*sizeof(WCHAR);
+ }
+
+ _wcsupr( (PWCHAR)ConfigParseTable[ CONFIG_BootName].Value);
+ _wcsupr( (PWCHAR)ConfigParseTable[ CONFIG_ConfigName].Value);
+
+ Call( JetPrepareUpdate( SesId, ConfigTableId, JET_prepInsert));
+
+
+ for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++ ) {
+ if ( ConfigParseTable[ Index].Name == NULL) {
+ continue;
+ }
+ JetError = JetSetColumn( SesId, ConfigTableId,
+ ConfigTable[ Index].ColumnId, ConfigParseTable[ Index].Value,
+ ConfigParseTable[ Index].Size, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("Index=%d(dec) JetError=%d", Index, JetError));
+ }
+ }
+ Call( JetSetColumn( SesId, ConfigTableId,
+ ConfigTable[ CONFIG_Flags].ColumnId, &Flags, sizeof(Flags), 0, NULL));
+
+ Call( JetUpdate( SesId, ConfigTableId, NULL, 0, NULL));
+ return( Cursor);
+}
+
+
+
+DWORD ProcessRplmgrIni( IN LPWSTR FilePath)
+{
+ PWCHAR Cursor;
+ PWCHAR String;
+ JET_COLUMNDEF ColumnDef;
+ JET_ERR JetError;
+ DWORD Index;
+ DWORD Offset;
+ CHAR IndexKey[ 255];
+
+ JetError = JetCreateTable( SesId, DbId, "config", CONFIG_TABLE_PAGE_COUNT,
+ CONFIG_TABLE_DENSITY, &ConfigTableId);
+
+ ColumnDef.cbStruct = sizeof( ColumnDef);
+ ColumnDef.columnid = 0;
+ ColumnDef.coltyp = JET_coltypLong;
+ ColumnDef.cbMax = 0;
+ ColumnDef.grbit = 0;
+
+ //
+ // Create columns. First initialize fields that do not change between
+ // addition of columns.
+ //
+ ColumnDef.cbStruct = sizeof(ColumnDef);
+ ColumnDef.columnid = 0;
+ ColumnDef.wCountry = 1;
+ ColumnDef.langid = 0x0409; // USA english
+ ColumnDef.cp = 1200; // UNICODE codepage
+ ColumnDef.wCollate = 0;
+ ColumnDef.cbMax = 0;
+ ColumnDef.grbit = 0; // variable length binary and text data.
+
+ for ( Index = 0; Index < CONFIG_TABLE_LENGTH; Index++ ) {
+
+ ColumnDef.coltyp = ConfigTable[ Index].ColumnType;
+ JetError = JetAddColumn( SesId, ConfigTableId,
+ ConfigTable[ Index].ColumnName, &ColumnDef,
+ NULL, 0, &ConfigTable[ Index].ColumnId);
+ if( JetError != ERROR_SUCCESS ) {
+ return( MapJetError( JetError));
+ }
+ }
+
+ Offset = AddKey( IndexKey, '+', ConfigTable[ CONFIG_ConfigName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, ConfigTableId, CONFIG_INDEX_ConfigName,
+ JET_bitIndexPrimary, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // +BootName+ConfigName index is used to enumerate all configurations for
+ // a given VendorId.
+ //
+ Offset = AddKey( IndexKey, '+', ConfigTable[ CONFIG_BootName].ColumnName);
+ Offset += AddKey( IndexKey + Offset, '+', ConfigTable[ CONFIG_ConfigName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, ConfigTableId, CONFIG_INDEX_BootNameConfigName,
+ JET_bitIndexUnique, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // Make config name a current index - used to validate profiles.
+ //
+ JetError = JetSetCurrentIndex( SesId, ConfigTableId, CONFIG_INDEX_ConfigName);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("SetCurrentIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ String = ReadTextFile( FilePath, RplmgrIniFile, MAX_RPLMGR_INI_FILE_SIZE);
+ if ( String == NULL) {
+ return( GetLastError());
+ }
+
+ //
+ // If current line is the beginning of configuration, we process
+ // that configuration (note that this processing has the side effect of
+ // advancing the cursor), else we just advance the cursor.
+ //
+ for ( Cursor = GetFirstLine( String); *Cursor != 0; NOTHING) {
+ Offset = OffsetAfterComment( Cursor);
+ if ( StringISpaceEqual( Cursor+Offset, CONFIG_BEGIN)) {
+ Cursor = ProcessConfig( Cursor);
+ } else {
+ Cursor = GetNextLine( Cursor);
+
+ }
+ }
+
+ if ( GlobalFree( String) != NULL) {
+ RplAssert( TRUE, ("GlobalFree: Error=%d", GetLastError()));
+ }
+
+ return( ERROR_SUCCESS);
+}
+
+
+VOID ConfigPruneTable( VOID)
+/*++
+ Eliminate config records that do not have a corresponding
+ boot block record defined.
+--*/
+{
+ WCHAR Name[ 20];
+ DWORD NameSize;
+ JET_ERR ForJetError;
+ JET_ERR JetError;
+
+ for ( ForJetError = JetMove( SesId, ConfigTableId, JET_MoveFirst, 0);
+ ForJetError == JET_errSuccess;
+ ForJetError = JetMove( SesId, ConfigTableId, JET_MoveNext, 0)) {
+
+ JetError = JetRetrieveColumn( SesId, ConfigTableId,
+ ConfigTable[ CONFIG_BootName].ColumnId, Name,
+ sizeof( Name), &NameSize, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
+ Call( JetDelete( SesId, ConfigTableId));
+ continue;
+ }
+ if ( !FindBoot( Name)) {
+#ifdef RPL_DEBUG_ALL
+ WCHAR Value[ 20];
+ JetRetrieveColumn( SesId, ConfigTableId,
+ ConfigTable[ CONFIG_ConfigName].ColumnId, Value,
+ sizeof( Value), &NameSize, 0, NULL);
+ printf("Deleting config %ws since boot %ws was not found\n",
+ Value, Name);
+#endif
+ Call( JetDelete( SesId, ConfigTableId));
+ continue;
+ }
+ }
+}
+
+
+BOOL FindConfig( IN PWCHAR Name)
+{
+ JET_ERR JetError;
+
+ JetError = JetMove( SesId, ConfigTableId, JET_MoveFirst, 0);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("JetMove failed err=%d", JetError));
+ return( FALSE);
+ }
+ JetError = JetMakeKey( SesId, ConfigTableId, Name,
+ ( wcslen( Name) + 1) * sizeof(WCHAR), JET_bitNewKey);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("MakeKey failed err=%d", JetError));
+ return( FALSE);
+ }
+ JetError = JetSeek( SesId, ConfigTableId, JET_bitSeekEQ);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("JetSeek for %ws failed err=%d", Name, JetError));
+ return( FALSE);
+ }
+ return( TRUE);
+}
+
+
+VOID ConfigListTable( VOID)
+{
+ ListTable( CONFIG_TABLE_NAME, ConfigTable[ CONFIG_ConfigName].ColumnName,
+ CONFIG_INDEX_ConfigName);
+}
+
diff --git a/private/net/svcdlls/rpl/convert/convert.rc b/private/net/svcdlls/rpl/convert/convert.rc
new file mode 100644
index 000000000..bec8ec87c
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/convert.rc
@@ -0,0 +1,12 @@
+#include <windows.h>
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_APP
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "RemoteBoot Conversion Utility"
+#define VER_INTERNALNAME_STR "rplcnv.exe"
+#define VER_ORIGINALFILENAME_STR "rplcnv.exe"
+
+#include "common.ver"
+
+1 11 MSG00001.bin
diff --git a/private/net/svcdlls/rpl/convert/debug.c b/private/net/svcdlls/rpl/convert/debug.c
new file mode 100644
index 000000000..918c93752
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/debug.c
@@ -0,0 +1,76 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ debug.c
+
+Abstract:
+
+ Debugging module.
+
+Author:
+
+ Jon Newman 26 - April - 1994
+
+Environment:
+
+ User mode
+
+Revision History :
+
+ Built from server\debug.c
+
+--*/
+
+#include "local.h"
+#include "rpldebug.h"
+
+#ifdef RPL_DEBUG
+
+#define RPL_PROMPT "[Rpl] "
+
+// int RG_DebugLevel = -1; // max debugging
+// int RG_DebugLevel = 0; // no debugging, for public use
+
+int RG_DebugLevel; // needed by other modules
+int RG_Assert; // needed by other modules
+
+char RG_DebugPublicBuffer[ 120];
+
+#define RPL_DEFAULT_DEBUG_LEVEL ( RPL_DEBUG_FLOW | \
+ RPL_DEBUG_SERVER | \
+ RPL_DEBUG_MAJOR )
+
+#define RPL_MAXIMUM_DEBUG_LEVEL (-1L)
+
+
+
+VOID _CRTAPI1 RplDebugPrint( CONST CHAR * format, ...)
+{
+ va_list arglist;
+
+ va_start( arglist, format);
+
+ strcpy( RG_DebugPublicBuffer, RPL_PROMPT );
+ vsprintf( RG_DebugPublicBuffer + sizeof( RPL_PROMPT) - 1, format, arglist);
+ DbgPrint( "%s\n", RG_DebugPublicBuffer); // for kernel debugger
+ printf( "%s\n", RG_DebugPublicBuffer); // for user debugger
+
+ if ( RG_Assert != 0) {
+ ASSERT( FALSE); // break for checked build
+ DbgPrint( "[RplSvc] Running checked version of service on a free build.\n");
+ printf( "[RplSvc] Running checked version of service on a free build.\n");
+ DbgUserBreakPoint();
+ }
+
+ va_end( arglist);
+
+} // RplDebugPrint
+
+
+#endif // RPL_DEBUG
+
+
+
diff --git a/private/net/svcdlls/rpl/convert/library.c b/private/net/svcdlls/rpl/convert/library.c
new file mode 100644
index 000000000..1014cbef2
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/library.c
@@ -0,0 +1,330 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ library.c
+
+Abstract:
+
+ Common routines used in CONVERT code.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Revision History:
+
+ Jon Newman (jonn) 06 - June - 1994
+ Convert file from OEM code page
+
+--*/
+
+#include "local.h"
+
+
+LPWSTR ReadTextFile(
+ IN LPWSTR FilePath,
+ IN LPWSTR FileName,
+ IN DWORD MaxFileSize
+ )
+/*++
+
+Routine Description:
+
+ Reads text file, converts its content from dbcs to unicode, and returns
+ a pointer to newly allocate unicode buffer.
+
+Arguments:
+
+Return Value:
+
+ Pointer to unicode buffer table if successful, NULL otherwise.
+
+--*/
+{
+ PBYTE DbcsString = NULL;
+ DWORD DbcsSize;
+ PWCHAR UnicodeString = NULL;
+ DWORD UnicodeSize;
+ int UnicodeStringLength;
+ HANDLE FileHandle;
+ DWORD BytesRead;
+ BOOL success = FALSE;
+ PWCHAR pWchar;
+ WCHAR CompleteFilePath[ MAX_PATH+1];
+ PWCHAR UseFilePath = FileName;
+
+ CompleteFilePath[0] = L'\0';
+ if ( FilePath != NULL && lstrlenW(FilePath) > 0) {
+ lstrcpyW( CompleteFilePath, FilePath);
+ if ( CompleteFilePath[ lstrlenW(CompleteFilePath)-1 ] != L'\\') {
+ lstrcatW( CompleteFilePath, L"\\");
+ }
+ if ( FileName != NULL) {
+ lstrcatW( CompleteFilePath, FileName );
+ }
+ UseFilePath = CompleteFilePath;
+ }
+
+ FileHandle = CreateFile( UseFilePath, GENERIC_READ, FILE_SHARE_READ,
+ NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0L);
+ if ( FileHandle == INVALID_HANDLE_VALUE) {
+ //
+ // Specifying a bad path (path with missing OS/2 rpl init files)
+ // is a common user error. Print out something for the user.
+ //
+ RplAssert( TRUE, ("CreateFile: Error = %d", GetLastError()));
+ RplPrintf1( RPLI_CVT_CannotOpenFile, UseFilePath);
+ goto exit;
+ }
+ DbcsSize = GetFileSize( FileHandle, NULL); // does not include 0x1A at the file end
+ if ( DbcsSize == INVALID_FILE_SIZE || DbcsSize > MaxFileSize) {
+ RplAssert( TRUE, ("DbcsSize = %d", DbcsSize));
+ goto exit;
+ }
+ DbcsString = GlobalAlloc( GMEM_FIXED, DbcsSize);
+ if ( DbcsString == NULL) {
+ RplAssert( TRUE, ("GlobalAlloc: Error = %d", GetLastError()));
+ goto exit;
+ }
+
+ UnicodeSize = ( DbcsSize + 1) * sizeof(WCHAR); // extra 1 for terminating NULL
+ UnicodeString = GlobalAlloc( GMEM_FIXED, UnicodeSize);
+ if ( UnicodeString == NULL) {
+ RplAssert( TRUE, ("GlobalAlloc: Error = %d", GetLastError()));
+ goto exit;
+ }
+
+ if ( !ReadFile( FileHandle, DbcsString, DbcsSize, &BytesRead, NULL)) {
+ RplAssert( TRUE, ("ReadFile: Error = %d", GetLastError()));
+ goto exit;
+ }
+
+ if ( BytesRead != DbcsSize) {
+ RplAssert( TRUE, ("BytesRead = %d, DbcsSize", BytesRead, DbcsSize));
+ goto exit;
+ }
+
+ UnicodeStringLength = MultiByteToWideChar(
+ CP_OEMCP, // file is in OEM codepage
+ MB_PRECOMPOSED, DbcsString, DbcsSize, UnicodeString, UnicodeSize);
+ if ( UnicodeStringLength == 0) {
+ RplAssert( TRUE, ("MultiByte...: Error = %d", GetLastError()));
+ goto exit;
+ }
+
+ //
+ // If file has END_OF_TEXT_FILE_CHAR, truncate the text there.
+ //
+ pWchar = wcschr( UnicodeString, END_OF_TEXT_FILE_CHAR);
+ if ( pWchar != NULL) {
+ *pWchar = 0;
+ }
+
+ success = TRUE;
+
+exit:
+
+ if ( FileHandle != INVALID_HANDLE_VALUE) {
+ (VOID)CloseHandle( FileHandle);
+ }
+ if ( DbcsString != NULL) {
+ GlobalFree( DbcsString);
+ }
+
+ if ( success != TRUE && UnicodeString != NULL) {
+ GlobalFree( UnicodeString);
+ UnicodeString = NULL;
+ }
+
+ return( UnicodeString);
+
+} // ReadTextFile
+
+
+PWCHAR GetFirstLine( PWCHAR Cursor)
+/*++
+ Skips all white characters.
+--*/
+//
+{
+ // Read empty chars if there's some.
+ while( *Cursor != 0 && iswspace(*Cursor)) {
+ Cursor++;
+ }
+
+ return( Cursor);
+}
+
+
+
+PWCHAR GetNextLine( PWCHAR Cursor)
+/*++
+ Skips to the end of the current line.
+ Then skips all white characters.
+--*/
+//
+{
+ // Read to end of line.
+ do {
+ Cursor++;
+ } while ( *Cursor != 0 && *Cursor != NEW_LINE_CHAR);
+
+ // Read empty chars if there's some.
+ while( *Cursor != 0 && iswspace(*Cursor)) {
+ Cursor++;
+ }
+
+ return( Cursor);
+}
+
+
+DWORD OffsetAfterComment( IN PWCHAR Cursor)
+/*++
+ Returns the offset of the first non-white non-newline character
+ after an optional RPL_COMMENT. This routine does not & should
+ not cross line boundaries (this is reserved for GetNewLine).
+--*/
+{
+#define RPL_COMMENT L";*;"
+#define RPL_COMMENT_LENGTH (sizeof(RPL_COMMENT)/sizeof(WCHAR) - 1)
+
+ PWCHAR End;
+
+ if ( wcsncmp( Cursor, RPL_COMMENT, RPL_COMMENT_LENGTH)) {
+ return( 0); // there is no RPL_COMMENT
+ }
+ for ( End = Cursor + RPL_COMMENT_LENGTH;
+ *End != 0 && *End != NEW_LINE_CHAR && iswspace(*End);
+ End++) {
+ NOTHING;
+ }
+ if ( *End == NEW_LINE_CHAR) {
+ //
+ // We went to far. Must decrement end pointer or
+ // GetNewLine() will advance to the second next line.
+ //
+ End--;
+ }
+ return( (DWORD)(End - Cursor));
+}
+
+
+BOOL Find( IN JET_TABLEID TableId, IN PWCHAR Name)
+{
+ JET_ERR JetError;
+
+ JetError = JetMove( SesId, TableId, JET_MoveFirst, 0);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("JetMove failed err=%d", JetError));
+ return( FALSE);
+ }
+ JetError = JetMakeKey( SesId, TableId, Name,
+ ( wcslen( Name) + 1) * sizeof(WCHAR), JET_bitNewKey);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("MakeKey failed err=%d", JetError));
+ return( FALSE);
+ }
+ JetError = JetSeek( SesId, TableId, JET_bitSeekEQ);
+ if ( JetError != JET_errSuccess) {
+ if ( JetError == JET_errRecordNotFound) {
+ //
+ // This is an expected error => no break for this.
+ //
+ RplDbgPrint(("JetSeek for %ws failed with error = %d.\n", Name, JetError));
+ } else {
+ RplAssert( TRUE, ("JetSeek failed err=%d", JetError));
+ }
+ return( FALSE);
+ }
+ return( TRUE);
+}
+
+
+VOID Enum( IN JET_TABLEID TableId, IN JET_COLUMNID ColumnId, IN PCHAR IndexName)
+{
+ WCHAR Name[ 20];
+ DWORD NameSize;
+ JET_ERR ForJetError;
+ JET_ERR JetError;
+
+ Call( JetSetCurrentIndex( SesId, TableId, IndexName));
+
+ for ( ForJetError = JetMove( SesId, TableId, JET_MoveFirst, 0);
+ ForJetError == JET_errSuccess;
+ ForJetError = JetMove( SesId, TableId, JET_MoveNext, 0)) {
+
+ JetError = JetRetrieveColumn( SesId, TableId,
+ ColumnId, Name, sizeof( Name), &NameSize, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
+ continue;
+ }
+ RplDbgPrint(( "%ws\n", Name));
+ }
+}
+
+
+VOID ListTable( IN PCHAR TableName, IN PCHAR ColumnName, IN PCHAR IndexName)
+{
+ JET_TABLEID TableId;
+ JET_COLUMNDEF ColumnDef;
+
+ Call( JetOpenTable( SesId, DbId, TableName, NULL, 0,
+ JET_bitTableDenyWrite, &TableId));
+
+ Call( JetGetTableColumnInfo( SesId, TableId, ColumnName, &ColumnDef,
+ sizeof( ColumnDef), JET_ColInfo));
+
+ RplDbgPrint(( "\tTable: %s\n", TableName));
+
+ Enum( TableId, ColumnDef.columnid, IndexName);
+
+ Call( JetCloseTable( SesId, TableId));
+}
+
+
+PWCHAR AddFileExtension(
+ IN PWCHAR FilePath,
+ IN PWCHAR FileExtension,
+ IN BOOLEAN ExtensionOK
+ )
+{
+#define DOT_CHAR L'.'
+#define BACK_SLASH_CHAR L'\\'
+ PWCHAR FilePathEx;
+ PWCHAR pDot;
+ DWORD Length;
+ DWORD Error;
+
+ if ( FilePath == NULL) {
+ RplAssert( TRUE, ("FilePath is NULL"));
+ return( NULL);
+ }
+
+ pDot = wcsrchr( FilePath, DOT_CHAR);
+ if ( pDot != NULL) {
+ //
+ // Found a DOT. FilePath may have an extension.
+ //
+ if ( wcschr( pDot, BACK_SLASH_CHAR) == NULL) {
+ //
+ // There is no backslash after the DOT. FilePath has an extension.
+ // Return NULL if caller insists that file should have no extension.
+ //
+ return( ExtensionOK ? FilePath : NULL);
+ }
+ }
+ Length = wcslen( FilePath) + wcslen( FileExtension);
+ FilePathEx = GlobalAlloc( GMEM_FIXED, (Length + 1) * sizeof(WCHAR));
+ if ( FilePathEx == NULL) {
+ Error = GetLastError();
+ RplAssert( TRUE, ("GlobalAlloc: Error = %d", Error));
+ return( NULL);
+ }
+ wcscpy( FilePathEx, FilePath);
+ wcscat( FilePathEx, FileExtension);
+ return( FilePathEx);
+}
diff --git a/private/net/svcdlls/rpl/convert/local.h b/private/net/svcdlls/rpl/convert/local.h
new file mode 100644
index 000000000..658da46bf
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/local.h
@@ -0,0 +1,227 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ local.h
+
+Abstract:
+
+ Main include file for Remote initial Program Load CONVERT program.
+ This program converts from RPL.MAP & RPLMGR.INI, used in OS/2
+ lm2.0 and up, to NT database.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Revision History:
+
+--*/
+
+#include <nt.h> // ntexapi.h\NtQuerySystemTime
+#include <ntrtl.h> // RtlTimeToSecondsSince1970
+#include <nturtl.h>
+
+#include <windows.h> // DWORD, IN, File APIs, etc.
+#include <stdlib.h>
+#include <lmcons.h>
+
+#include <stdio.h> // vsprintf
+#include <ctype.h> // isspace
+
+#include <lmerr.h> // NERR_RplBootStartFailed - used to be here
+
+//
+#include <lmapibuf.h> // NetApiBufferFree
+#include <netlib.h>
+
+#include <lmsvc.h>
+
+#include <lmalert.h> // STD_ALERT ALERT_OTHER_INFO
+
+#include <lmerrlog.h>
+#include <alertmsg.h>
+#include <lmserver.h>
+#include <netlib.h>
+#include <netlock.h> // Lock data types, functions, and macros.
+#include <thread.h> // FORMAT_NET_THREAD_ID, NetpCurrentThread().
+
+#include <lmshare.h> // PSHARE_INFO_2
+#include <lmaccess.h> // NetGroupGetInfo
+#include <lmconfig.h> // NetConfigGet
+#include <nb30.h> // NCB
+
+#include <lmrpl.h>
+
+//
+// Global types and constants (used in all RPL server files).
+//
+
+#include <riplcons.h> // includes __JET500 flag
+#include <jet.h>
+#include <rpllib.h> // AddKey(), MapJetError(), FillTcpIpString()
+
+#include <rpldb.h>
+#include "nlstxt.h" // RPLI_CVT manifests
+
+#define EQUALS_CHAR L'='
+
+#define RPL_BUGBUG_ERROR 10999 // need to get rid of these
+
+#if DBG
+#define RPL_DEBUG // used in rpldata.h
+#endif
+
+//
+// Declare/Define all global variables.
+//
+
+#include "rpldata.h" // defines/declares global data structures
+
+//
+// jet call macros:
+// Call - jet call ignore error
+// CallR - jet call RETURN on error
+// CallB - jet call return BOOLEAN (false) on error
+// CallM - jet call return MAPPED error
+//
+
+#ifdef RPL_DEBUG
+
+#define RplDbgPrint( _x_) printf( "[DebugPrint] "); printf _x_
+
+#define RplBreakPoint() if ( DebugLevel) DbgUserBreakPoint()
+
+#define RplAssert( DBG_CONDITION, DBG_PRINT_ARGUMENTS) \
+ { \
+ if ( DBG_CONDITION) { \
+ RplDbgPrint( DBG_PRINT_ARGUMENTS); \
+ RplDbgPrint((" File %s, Line %d\n", __FILE__, __LINE__)); \
+ RplBreakPoint(); \
+ } \
+ }
+#define Call( fn ) \
+ { \
+ int _JetError = fn; \
+ if ( _JetError != JET_errSuccess) { \
+ printf("File = %s, Line = %d, _JetError = %d\n", __FILE__, __LINE__, _JetError); \
+ if ( _JetError < 0) { \
+ RplBreakPoint(); \
+ } \
+ } \
+ }
+#define CallR( fn ) \
+ { \
+ int _JetError = fn; \
+ if ( _JetError != JET_errSuccess) { \
+ printf("File = %s, Line = %d, _JetError = %d\n", __FILE__, __LINE__, _JetError); \
+ if ( _JetError < 0) { \
+ RplBreakPoint(); \
+ return; \
+ } \
+ } \
+ }
+
+#define CallB( fn ) \
+ { \
+ int _JetError = fn; \
+ if ( _JetError != JET_errSuccess) { \
+ printf("File = %s, Line = %d, _JetError = %d\n", __FILE__, __LINE__, _JetError); \
+ if ( _JetError < 0) { \
+ RplBreakPoint(); \
+ return( FALSE); \
+ } \
+ } \
+ }
+#define CallM( fn ) \
+ { \
+ int _JetError = fn; \
+ if ( _JetError != JET_errSuccess) { \
+ printf("File = %s, Line = %d, _JetError = %d\n", __FILE__, __LINE__, _JetError); \
+ if ( _JetError < 0) { \
+ RplBreakPoint(); \
+ return( NERR_RplInternal); \
+ } \
+ } \
+ }
+#define CallJ( fn ) \
+ { \
+ int _JetError = fn; \
+ if ( _JetError != JET_errSuccess) { \
+ printf("File = %s, Line = %d, _JetError = %d\n", __FILE__, __LINE__, _JetError); \
+ if ( _JetError < 0) { \
+ RplBreakPoint(); \
+ Error = NERR_RplInternal; \
+ goto cleanup; \
+ } \
+ } \
+ }
+
+#else
+#define RplDbgPrint( _x_)
+#define RplBreakPoint()
+#define RplAssert( DBG_CONDITION, DBG_PRINT_ARGUMENTS)
+#define Call( fn ) { if ( fn < 0) { NOTHING;} }
+#define CallR( fn ) { if ( fn < 0) { return;} }
+#define CallB( fn ) { if ( fn < 0) { return( FALSE);} }
+#define CallM( fn ) \
+ { \
+ int _JetError = fn; \
+ if ( _JetError < 0) { \
+ return( NERR_RplInternal); \
+ } \
+ }
+#define CallJ( fn ) \
+ { \
+ int _JetError = fn; \
+ if ( _JetError < 0) { \
+ Error = NERR_RplInternal; \
+ goto cleanup; \
+ } \
+ }
+#endif
+
+
+LPWSTR ReadTextFile( IN LPWSTR FilePath, IN LPWSTR FileName, IN DWORD MaxFileSize);
+PWCHAR GetFirstLine( PWCHAR Cursor);
+PWCHAR GetNextLine( PWCHAR Cursor);
+DWORD OffsetAfterComment( IN PWCHAR Cursor);
+BOOL Find( IN JET_TABLEID TableId, IN PWCHAR Name);
+VOID Enum( IN JET_TABLEID TableId, IN JET_COLUMNID ColumnId, IN PCHAR ndexName);
+VOID ListTable( IN PCHAR TableName, IN PCHAR ColumnName, IN PCHAR IndexName);
+PWCHAR AddFileExtension(
+ IN PWCHAR FilePath,
+ IN PWCHAR FileExtension,
+ IN BOOLEAN ExtensionOK
+ );
+
+DWORD BootCreateTable( VOID);
+VOID ProcessBoot( PWCHAR * Fields);
+VOID BootListTable( VOID);
+BOOL FindBoot( IN PWCHAR BootName);
+
+DWORD ProcessRplmgrIni( IN LPWSTR FilePath );
+BOOL FindConfig( IN PWCHAR ConfigName);
+VOID ConfigPruneTable( VOID);
+VOID ConfigListTable( VOID);
+DWORD CloseConfigTable( VOID);
+
+DWORD ProfileCreateTable( VOID);
+BOOL FindProfile( IN PWCHAR ProfileName);
+VOID ProfileListTable( VOID);
+VOID ProcessProfile( PWCHAR * Fields);
+VOID ProfilePruneTable( VOID);
+
+DWORD WkstaCreateTable( VOID);
+VOID ProcessWksta( PWCHAR * Fields);
+VOID WkstaPruneTable( VOID);
+VOID WkstaListTable( VOID);
+BOOL ListWkstaInfo( IN PWCHAR AdapterName);
+
+DWORD AdapterCreateTable( VOID);
+
+DWORD VendorCreateTable( VOID);
+
+
diff --git a/private/net/svcdlls/rpl/convert/makefile b/private/net/svcdlls/rpl/convert/makefile
new file mode 100644
index 000000000..6ee4f43fa
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/makefile
@@ -0,0 +1,6 @@
+#
+# DO NOT EDIT THIS FILE!!! Edit .\sources. if you want to add a new source
+# file to this component. This file merely indirects to the real make file
+# that is shared by all the components of NT OS/2
+#
+!INCLUDE $(NTMAKEENV)\makefile.def
diff --git a/private/net/svcdlls/rpl/convert/makefile.inc b/private/net/svcdlls/rpl/convert/makefile.inc
new file mode 100644
index 000000000..f28149e83
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/makefile.inc
@@ -0,0 +1,4 @@
+nlstxt.rc: msg00001.bin
+
+nlstxt.h msg00001.bin: nlstxt.mc
+ mc -v nlstxt.mc
diff --git a/private/net/svcdlls/rpl/convert/nlstxt.mc b/private/net/svcdlls/rpl/convert/nlstxt.mc
new file mode 100644
index 000000000..8b8e47f8e
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/nlstxt.mc
@@ -0,0 +1,214 @@
+;/*++
+;
+;Copyright (c) 1992 Microsoft Corporation
+;
+;Module Name:
+;
+; rplimsg.h
+;
+;Abstract:
+;
+; Definitions for RPLCNV command private errors.
+;
+;Author:
+;
+; Jon Newman (jonn) 21 - April - 1994
+;
+;Revision History:
+;
+; 21-Apr-1994 jonn
+; templated from AT command
+;
+;Notes:
+;
+; This file is generated by the MC tool from the lmatmsg.mc file.
+;
+;--*/
+
+MessageId=11000 SymbolicName=RPLI_CVT_NoMDB
+Language=English
+File system.mdb is absent.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_StopService
+Language=English
+Remote boot service must be stopped for this program to run.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_InitError
+Language=English
+Unexpected initialization error.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_CannotOpenFile
+Language=English
+Cannot open %1!ws!%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_ProfileInvalid
+Language=English
+Not converting %1!ws! profile because its name is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_ProfileInvalidConfig
+Language=English
+Not converting %1!ws! profile because its configuration %2!ws!
+is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_ProfileInvalidFit
+Language=English
+Not converting %1!ws! profile because its fit file %2!ws!
+is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_ProfileInvalidBoot
+Language=English
+Not converting %1!ws! profile because its boot block name %2!ws!
+is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_USAGE
+Language=English
+The RPLCNV utility (RemoteBoot conversion program) converts
+rpl.map and rplmgr.ini used by OS/2 LANMAN Remoteboot service into system.mdb
+and rplsvc.mdb files used by NT Remoteboot service. Install the Remoteboot
+service before running the Remoteboot conversion program, and
+make sure a copy of the original system.mdb file is in
+the root of the RPL file tree as specified during RPL installation.%n
+%n
+RPLCNV [Path]%n
+%n
+Path Specifies a fully qualified path to the directory containing the
+rpl.map and rplmgr.ini files used by OS/2 LANMAN RemoteBoot service.
+If this parameter is omitted it is assumed that these files are in the
+current directory or the root of the RPL file tree.
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_NoMAP_INI
+Language=English
+Files rpl.map and/or rplmgr.ini are absent.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_NoSystemMdb
+Language=English
+File system.mdb is absent from the root of the RPL file tree.
+RPLCNV cannot convert rpl.map and rplmgr.ini unless a copy
+of the original system.mdb file is in the root of the RPL file tree.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_RplsvcMdbExists
+Language=English
+File rplsvc.mdb already exists in the root of the RPL file tree.
+RPLCNV will not create a new one until the existing one is moved,
+renamed or deleted.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_OldSystemMdb
+Language=English
+File system.mdb exists in the root of the RPL file tree but is not
+a copy of the original system.mdb file. RPLCNV cannot convert rpl.map
+and rplmgr.ini unless a copy of the original system.mdb file is in the
+root of the RPL file tree.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_BootNameTooLong
+Language=English
+Boot block record with name %1!ws! is not converted because
+its name is too long or invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_BbcFileTooLong
+Language=English
+Boot block record with name %1!ws! is not converted because
+path to boot block configuration file %2!ws! is too long or
+invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_BadVendorName
+Language=English
+Boot block record with name %1!ws! is not converted because
+vendor name %2!ws! is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaInvalid
+Language=English
+Workstation record with name %1!ws! is not converted because
+its name is too long or invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaInvalidAdapter
+Language=English
+Workstation record with name %1!ws! is not converted because
+adapter id %2!ws! is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaInvalidLogon
+Language=English
+Workstation record with name %1!ws! is not converted because
+remoteboot username/password prompting field %2!ws! is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaInvalidFit
+Language=English
+Workstation record with name %1!ws! is not converted because
+fit name %2!ws! is too long or invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaInvalidSharing
+Language=English
+Workstation record with name %1!ws! is not converted because
+sharing type %2!ws! is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaDisabledBoot
+Language=English
+Workstation record with name %1!ws! is not converted since its
+reference to block record %2!ws! is disabled.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaInvalidBoot
+Language=English
+Workstation record with name %1!ws! is not converted because
+boot block name %2!ws! is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaInvalidProfile
+Language=English
+Workstation record with name %1!ws! is not converted because
+profile name %2!ws! is invalid.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaDuplicateName
+Language=English
+Workstation record is not converted because it uses a duplicate computer name
+(%1!ws!) or a duplicate adapter id (%2!ws!).%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_WkstaDefaultProfile
+Language=English
+Workstation record with computer name %1!ws! is not converted
+because it uses the obsolete DEFAULT profile.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_ConfigNoPersonalFIT
+Language=English
+Not converting %1!ws! configuration because it does not have
+a fit file for personal profiles.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_ConfigNoOS2
+Language=English
+Not converting %1!ws! configuration because it is an OS/2
+client configuration.%n
+.
+
+MessageId=+1 SymbolicName=RPLI_CVT_ConfigInvalid
+Language=English
+Not converting %1!ws! configuration because the value of
+keyword %2!ws! is absent or invalid.%n
+.
+
+
+
+ \ No newline at end of file
diff --git a/private/net/svcdlls/rpl/convert/profile.c b/private/net/svcdlls/rpl/convert/profile.c
new file mode 100644
index 000000000..f8f0c14a8
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/profile.c
@@ -0,0 +1,270 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ profile.c
+
+Abstract:
+
+ Creates profile table. Parses old style RPL.MAP profile records and
+ creates corresponding entries in jet database table.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Revision History:
+
+--*/
+
+#include "local.h"
+#define RPLPROFILE_ALLOCATE
+#include "profile.h"
+#undef RPLPROFILE_ALLOCATE
+
+
+DWORD ProfileCreateTable( VOID)
+{
+ JET_COLUMNDEF ColumnDef;
+ JET_ERR JetError;
+ DWORD index;
+ DWORD Offset;
+ CHAR IndexKey[ 255];
+
+ JetError = JetCreateTable( SesId, DbId, PROFILE_TABLE_NAME,
+ PROFILE_TABLE_PAGE_COUNT, PROFILE_TABLE_DENSITY, &ProfileTableId);
+
+ //
+ // Create columns. First initalize fields that do not change between
+ // addition of columns.
+ //
+ ColumnDef.cbStruct = sizeof(ColumnDef);
+ ColumnDef.columnid = 0;
+ ColumnDef.wCountry = 1;
+ ColumnDef.langid = 0x0409; // USA english
+ ColumnDef.cp = 1200; // UNICODE codepage
+ ColumnDef.wCollate = 0;
+ ColumnDef.cbMax = 0;
+ ColumnDef.grbit = 0; // variable length binary and text data.
+
+ for ( index = 0; index < PROFILE_TABLE_LENGTH; index++ ) {
+
+ ColumnDef.coltyp = ProfileTable[ index].ColumnType;
+
+ Call( JetAddColumn( SesId, ProfileTableId,
+ ProfileTable[ index].ColumnName, &ColumnDef,
+ NULL, 0, &ProfileTable[ index].ColumnId));
+ }
+
+ Offset = AddKey( IndexKey, '+', ProfileTable[ PROFILE_ProfileName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, ProfileTableId, PROFILE_INDEX_ProfileName,
+ JET_bitIndexPrimary, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // +BootName+ProfileName index is used to enumerate all profiles for
+ // a given VendorId.
+ //
+ Offset = AddKey( IndexKey, '+', ProfileTable[ PROFILE_BootName].ColumnName);
+ Offset += AddKey( IndexKey + Offset, '+', ProfileTable[ PROFILE_ProfileName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, ProfileTableId, PROFILE_INDEX_BootNameProfileName,
+ JET_bitIndexUnique, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // +ConfigName+ProfileName index is used to find if a there is a
+ // profile record for a given configuration record
+ //
+ Offset = AddKey( IndexKey, '+', ProfileTable[ PROFILE_ConfigName].ColumnName);
+ Offset += AddKey( IndexKey + Offset, '+', ProfileTable[ PROFILE_ProfileName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, ProfileTableId, PROFILE_INDEX_ConfigNameProfileName,
+ JET_bitIndexUnique, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // Make profile name a current index - used to validate wkstas.
+ //
+ JetError = JetSetCurrentIndex( SesId, ProfileTableId, PROFILE_INDEX_ProfileName);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("SetCurrentIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ return( ERROR_SUCCESS);
+}
+
+
+VOID ProcessProfile( PWCHAR * Fields)
+{
+//
+// PROFILE_COMMENT_INDEX would be equal to 15 if we were to count fields
+// from 1 (not 0) and count ",,," as a single field (not 3 fields).
+//
+#define PROFILE_FITFILE_INDEX 3 // common fit file name
+#define PROFILE_CONFIGNAME_INDEX 12 // configuration name
+#define PROFILE_BOOTNAME_INDEX 13 // boot block identifier
+#define PROFILE_PROFILENAME_INDEX 15 // profile name
+#define PROFILE_COMMENT_INDEX 16 // profile comment
+
+ PWCHAR ProfileComment;
+ PWCHAR ProfileName;
+ PWCHAR BootName;
+ PWCHAR ConfigName;
+ PWCHAR FitShared;
+ PWCHAR FitPersonal;
+ DWORD Flags;
+
+ ProfileName = Fields[ PROFILE_PROFILENAME_INDEX];
+ if ( !ValidName( ProfileName, RPL_MAX_PROFILE_NAME_LENGTH, TRUE)) {
+ RplPrintf1( RPLI_CVT_ProfileInvalid, ProfileName);
+ RplAssert( TRUE, ("Bad profile name %ws", ProfileName));
+ return;
+ }
+ _wcsupr( ProfileName);
+
+ FitShared = AddFileExtension( Fields[ PROFILE_FITFILE_INDEX], L".FIT", FALSE);
+ FitPersonal = AddFileExtension( Fields[ PROFILE_FITFILE_INDEX], L"P.FIT", FALSE);
+ if ( !ValidName( FitShared, RPL_MAX_STRING_LENGTH, TRUE) ||
+ !ValidName( FitPersonal, RPL_MAX_STRING_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_ProfileInvalidFit, ProfileName, Fields[ PROFILE_FITFILE_INDEX]);
+ RplAssert( TRUE, ("Bad fit name %ws", Fields[ PROFILE_FITFILE_INDEX]));
+ return;
+ }
+
+ ConfigName = Fields[ PROFILE_CONFIGNAME_INDEX];
+ if ( !ValidName( ConfigName, RPL_MAX_CONFIG_NAME_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_ProfileInvalidConfig, ProfileName, ConfigName);
+ RplAssert( TRUE, ("Bad config name %ws", ConfigName));
+ return;
+ }
+ _wcsupr( ConfigName);
+
+ BootName = Fields[ PROFILE_BOOTNAME_INDEX];
+ RplAssert( *BootName != L'R', ("BootBlockId=%ws", BootName));
+ BootName++; // skip leading 'R' in server name
+ if ( !ValidName( BootName, RPL_MAX_BOOT_NAME_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_ProfileInvalidBoot, ProfileName, Fields[ PROFILE_BOOTNAME_INDEX]);
+ RplAssert( TRUE, ("Bad boot name %ws", Fields[ PROFILE_BOOTNAME_INDEX]));
+ return;
+ }
+ _wcsupr( BootName);
+
+ ProfileComment = Fields[ PROFILE_COMMENT_INDEX];
+ if ( RPL_STRING_TOO_LONG( ProfileComment)) {
+ ProfileComment[ RPL_MAX_STRING_LENGTH] = 0; // silently truncate it
+ }
+
+ Call( JetPrepareUpdate( SesId, ProfileTableId, JET_prepInsert));
+
+ Call( JetSetColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_ProfileName].ColumnId, ProfileName,
+ (wcslen( ProfileName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_ProfileComment].ColumnId, ProfileComment,
+ (wcslen( ProfileComment) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_ConfigName].ColumnId, ConfigName,
+ (wcslen( ConfigName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_BootName].ColumnId, BootName,
+ (wcslen( BootName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_FitShared].ColumnId, FitShared,
+ (wcslen( FitShared) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_FitPersonal].ColumnId, FitPersonal,
+ (wcslen( FitPersonal) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Flags = 0;
+ Call( JetSetColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_Flags].ColumnId, &Flags, sizeof(Flags), 0, NULL));
+
+
+ Call( JetUpdate( SesId, ProfileTableId, NULL, 0, NULL));
+}
+
+
+VOID ProfilePruneTable( VOID)
+/*++
+ Eliminate profile records that do not have a corresponding config record
+ defined.
+--*/
+{
+ WCHAR Name[ 20];
+ DWORD NameSize;
+ JET_ERR ForJetError;
+ JET_ERR JetError;
+
+ for ( ForJetError = JetMove( SesId, ProfileTableId, JET_MoveFirst, 0);
+ ForJetError == JET_errSuccess;
+ ForJetError = JetMove( SesId, ProfileTableId, JET_MoveNext, 0)) {
+
+ JetError = JetRetrieveColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_BootName].ColumnId, Name,
+ sizeof( Name), &NameSize, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
+ Call( JetDelete( SesId, ProfileTableId));
+ continue;
+ }
+ if ( !FindBoot( Name)) {
+ Call( JetDelete( SesId, ProfileTableId));
+ continue;
+ }
+
+ JetError = JetRetrieveColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_ConfigName].ColumnId, Name,
+ sizeof( Name), &NameSize, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
+ Call( JetDelete( SesId, ProfileTableId));
+ continue;
+ }
+ if ( !FindConfig( Name)) {
+ WCHAR ProfileName[ 20];
+ DWORD ProfileNameSize;
+ JetError = JetRetrieveColumn( SesId, ProfileTableId,
+ ProfileTable[ PROFILE_ProfileName].ColumnId, ProfileName,
+ sizeof( ProfileName), &ProfileNameSize, 0, NULL);
+ if ( JetError == JET_errSuccess && ProfileNameSize <= sizeof( ProfileName) ) {
+ RplPrintf2( RPLI_CVT_ProfileInvalidConfig, ProfileName, Name);
+ }
+ Call( JetDelete( SesId, ProfileTableId));
+ continue;
+ }
+ }
+}
+
+
+
+BOOL FindProfile( IN PWCHAR ProfileName)
+{
+ return( Find( ProfileTableId, ProfileName));
+}
+
+
+
+VOID ProfileListTable( VOID)
+{
+ ListTable( PROFILE_TABLE_NAME, ProfileTable[ PROFILE_ProfileName].ColumnName,
+ PROFILE_INDEX_ProfileName);
+}
diff --git a/private/net/svcdlls/rpl/convert/rpldata.h b/private/net/svcdlls/rpl/convert/rpldata.h
new file mode 100644
index 000000000..d62c9b2e5
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/rpldata.h
@@ -0,0 +1,47 @@
+/*++
+
+Copyright (c) 1993 Microsoft Corporation
+
+Module Name:
+
+ rpldata.h
+
+Abstract:
+
+ RPL covert global variables (declarations & definitions).
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Environment:
+
+ User mode
+
+Revision History :
+
+--*/
+
+//
+// rplmain.c will #include this file with RPLDATA_ALLOCATE defined.
+// That will cause each of these variables to be allocated.
+//
+#ifdef RPLDATA_ALLOCATE
+#define EXTERN
+#define INIT( _x) = _x
+#else
+#define EXTERN extern
+#define INIT( _x)
+#endif
+
+EXTERN JET_SESID SesId;
+EXTERN JET_DBID DbId;
+EXTERN JET_INSTANCE JetInstance;
+
+EXTERN CHAR G_ServiceDatabaseA[ MAX_PATH ];
+EXTERN WCHAR G_ServiceDirectoryW[ MAX_PATH ];
+
+#ifdef RPL_DEBUG
+EXTERN int DebugLevel;
+#endif
+
diff --git a/private/net/svcdlls/rpl/convert/rplmain.c b/private/net/svcdlls/rpl/convert/rplmain.c
new file mode 100644
index 000000000..a2643e0b6
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/rplmain.c
@@ -0,0 +1,740 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ rplmain.c
+
+Abstract:
+
+ Converts old style (OS/2) files RPL.MAP & RPLMGR.INI
+ into a new style database to be used with NT rpl server.
+
+ BUGBUG Should polish and make WIN32 application out of this.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Environment:
+
+ User mode
+
+Revision History :
+
+--*/
+
+#define RPLDATA_ALLOCATE
+#include "local.h"
+#undef RPLDATA_ALLOCATE
+#include <shellapi.h>
+#include "boot.h"
+#include "config.h"
+#include "profile.h"
+#include "wksta.h"
+#include "adapter.h"
+#include "vendor.h"
+
+#define COMMA_CHAR L','
+PWCHAR RplMapFile = L"rpl.map";
+WCHAR RG_NulWchar = 0; // used for empty entries in rpl.map
+//
+// RPL.MAP defines
+//
+#define MAX_RPL_MAP_FILE_SIZE 0xFFFE // BUGBUG some arbitrary value
+typedef enum _MAP_RECORD_TYPE {
+ RecordTypeComment = 0, // comment line in PRL.MAP file
+ RecordTypeBoot, // boot block records, documented in os/2 lm2.0 & up
+ RecordTypePcDosBoot, // boot block records, undocumented but supported
+ RecordTypeProfile, // profile record
+ RecordTypeUniqueAdapter,// wksta record containing unique adapter id
+ RecordTypeWildAdapter, // wksta record containing wildcards in adapter id
+ RecordTypeUnknown // unknown record
+} MAP_RECORD_TYPE;
+
+#define EXTENDED_BOOT_ENTRIES L"yyyyyyyyyyyy"
+#define EXTENDED_BOOT_ENTRIES2 L"RPL~Header~~"
+#define PCDOS_BOOT_ENTRIES L"xxxxxxxxxxxx"
+#define PCDOS_BOOT_ENTRIES2 L"PCDOS~Header"
+#define PROFILE_ADAPTER_ID L"000000000000" // first field of profile record
+
+
+
+#define MAX_RPL_FIELD 20 // max number of entries on rpl.map line
+
+
+
+
+BOOL StringsSpaceEqual( IN PWCHAR str1, IN PWCHAR str2 )
+/*++
+
+Routine Description:
+
+ Compare strings up to the first space or NULL character in each
+ string, returning TRUE if strings are equal, FALSE otherwise.
+
+Arguments:
+
+ str1 - first string
+ str2 - second string
+
+Return Value:
+
+ TRUE if strings are equal, FALSE otherwise.
+
+--*/
+{
+ WCHAR ch1;
+
+#ifdef NOT_YET
+ if ( str1 == NULL || str2 == NULL) {
+ str1 = (str1 != NULL) ? str1 : str2;
+ if ( str2 == NULL) {
+ return( TRUE); // both strings are NULL
+ }
+ while ( iswspace( *str1++)) {
+ NOTHING; // check if not NULL string contains spaces only
+ }
+ return( *str1 == 0);
+ }
+#endif // NOT_YET
+
+ //
+ // Compare strings until the first space or NULL character
+ // (in the first string) or until we find the first different character.
+ //
+ while ( (ch1 = *str1) && !iswspace(ch1) && ch1 == *str2) {
+ str1++, str2++;
+ }
+
+ //
+ // For strings to be equal, both characters must be NULL or space.
+ //
+ if ( (!ch1 || iswspace(ch1)) && (!(ch1 = *str2) || iswspace(ch1)))
+ {
+ return( TRUE);
+ }
+
+ return( FALSE);
+}
+
+
+BOOL IsWildAdapterName( IN PWCHAR Cursor)
+/*++
+
+Routine Description:
+
+ Returns TRUE if the input string may be the adapter id of a wksta group.
+
+ Adapter id must be terminated with space AND must have exactly
+ RPL_ADAPTER_NAME_LENGTH hex digits.
+
+Arguments:
+
+ Cursor - pointer to adapter id string
+
+Return Value:
+ Returns TRUE if input string may be a unique adapter id of a client,
+ else FALSE.
+
+--*/
+{
+ DWORD count = 0;
+ WCHAR ch;
+
+ for ( count = 0; (ch = *Cursor) == '?' || iswxdigit(ch); count++) {
+ Cursor++;
+ }
+
+ if ( !iswspace(ch) || count != RPL_ADAPTER_NAME_LENGTH) {
+ return( FALSE);
+ }
+
+ return( TRUE);
+}
+
+
+BOOL IsAdapterName( IN PWCHAR Cursor)
+/*++
+
+Routine Description:
+
+ Returns TRUE if the input string may be the adapter id of a wksta.
+
+ Adapter id must be terminated with space AND must have
+ exactly RPL_ADAPTER_NAME_LENGTH hex digits
+
+Arguments:
+
+ Cursor - pointer to adapter id string
+
+Return Value:
+ Returns TRUE if input string may be a unique adapter id of a client,
+ else FALSE.
+
+--*/
+{
+ DWORD count;
+
+ for ( count = 0; iswxdigit(*Cursor); count++) {
+ Cursor++;
+ }
+
+ if ( !iswspace(*Cursor) || count != RPL_ADAPTER_NAME_LENGTH) {
+ return( FALSE);
+ }
+ return( TRUE);
+}
+
+
+MAP_RECORD_TYPE RplGetRecordType( IN PWCHAR Cursor)
+/*++
+
+Routine Description:
+
+ Returns the type of a line in RPL.MAP.
+
+Arguments:
+ Cursor - pointer to line from RPL.map file
+
+Return Value:
+ Returns type of a line in RPL.map file
+
+--*/
+{
+ // strings can be either nul or space terminated
+
+ if ( *Cursor == COMMENT_CHAR) {
+
+ return( RecordTypeComment);
+ }
+
+ if ( StringsSpaceEqual( Cursor, EXTENDED_BOOT_ENTRIES) ||
+ StringsSpaceEqual( Cursor, EXTENDED_BOOT_ENTRIES2)) {
+
+ return( RecordTypeBoot);
+ }
+
+ if ( StringsSpaceEqual( Cursor, PCDOS_BOOT_ENTRIES) ||
+ StringsSpaceEqual( Cursor, PCDOS_BOOT_ENTRIES2)) {
+
+ return( RecordTypePcDosBoot);
+ }
+
+ if ( StringsSpaceEqual( Cursor, PROFILE_ADAPTER_ID)) {
+
+ return( RecordTypeProfile);
+ }
+
+ if ( IsAdapterName( Cursor)) {
+ return( RecordTypeUniqueAdapter);
+ }
+
+ if ( IsWildAdapterName( Cursor)) {
+ return( RecordTypeWildAdapter);
+ }
+
+ return( RecordTypeUnknown);
+}
+
+
+
+PWCHAR ScanChar(
+ IN PWCHAR String,
+ IN WCHAR ch
+ )
+/*++
+
+Routine Description:
+
+ Searches for the first desired character in the string. The string
+ should be NULL terminated.
+
+Arguments:
+ String - string which is NULL terminated
+ ch - character we are searching for
+
+Return Value:
+ Pointer to the first desired character (if there is such character),
+ else pointer to the last character before terminating NULL.
+
+--*/
+{
+ while ( *String && *String != ch) {
+ String++;
+ }
+ return( String);
+}
+
+
+PWCHAR ScanNonSpace( IN PWCHAR String)
+/*++
+
+Routine Description:
+ Returns pointer to the first non space character in the string.
+ This may be pointer to NULL if string has no space char.
+
+Arguments:
+ string - NULL terminated string to search in
+
+Return Value:
+ Pointer of the first non space character in the string.
+
+--*/
+{
+ while( iswspace(*String)) { // iswspace(0) is 0
+ String++;
+ }
+ return( String);
+}
+
+
+
+PWCHAR ScanSpace( IN PWCHAR String)
+/*++
+
+Routine Description:
+
+ Returns pointer to the first space character in the string if it
+ can find a space character in the string. Else, it returns pointer
+ to zero character ('\0').
+
+Arguments:
+ String - where we are searching for space character
+
+Return Value:
+ Pointer to the first space character (if there is a space char) or
+ pointer to zero.
+
+--*/
+{
+ while ( *String && !iswspace(*String)) {
+ String++;
+ }
+ return( String);
+}
+
+
+BOOL LineToWords(
+ IN PWCHAR Cursor,
+ IN PWCHAR * Fields,
+ IN DWORD FieldsLength
+ )
+/*++
+
+Routine Description:
+ Breaks the line the words and returns the pointer to a word (string) table.
+
+ Note that we do special line parsing when current table index is 9, 10
+ or 11. E.g. field ",,," of RPL.map line will result in three table
+ entries instead of just one.
+
+Arguments:
+ Cursor - ptr to line string
+ Fields - pointer to string table describing fields in RPL.MAP line
+ FieldsLength - max number of entries in fields string table,
+ not counting the terminal NULL entry
+Return Value:
+ None.
+
+--*/
+{
+#define FIRST_EXTRA_MEM 9
+#define LAST_EXTRA_MEM 11
+ PWCHAR str;
+ DWORD index;
+ DWORD length;
+
+
+ for ( index = 0; index < FieldsLength; index++) {
+
+ if (*Cursor) {
+
+ //
+ // check if extra mem field(s)
+ //
+
+ if ( index >= FIRST_EXTRA_MEM && index <= LAST_EXTRA_MEM) {
+ length = ScanChar( Cursor, COMMA_CHAR) - Cursor;
+ if ( Cursor[ length] == COMMA_CHAR) {
+ length++;
+ }
+ } else {
+ length = ScanSpace( Cursor) - Cursor;
+ }
+
+ if (length == 0 || (length == 1 && *Cursor == TILDE_CHAR)) {
+
+ Fields[ index] = &RG_NulWchar;
+
+ } else {
+
+ str = Fields[ index] = GlobalAlloc( GMEM_FIXED, (length + 1) * sizeof( WCHAR));
+ if ( str == NULL) {
+ return( FALSE);
+ }
+ memcpy( str, Cursor, length * sizeof( WCHAR));
+ str[ length] = 0;
+
+ // replace all TILDE_CHAR-s in the string
+ while (*(str = ScanChar( str, TILDE_CHAR )) == TILDE_CHAR) {
+ *str = SPACE_CHAR;
+ }
+ }
+ Cursor += length;
+
+ } else {
+ Fields[ index] = &RG_NulWchar;
+ }
+
+ //
+ // jump over spaces
+ //
+
+ Cursor = ScanNonSpace( Cursor);
+ }
+
+ Fields[ index] = NULL; // terminate the string table
+ return( TRUE);
+}
+
+
+DWORD ProcessRplMap( IN LPWSTR FilePath)
+{
+ PWCHAR Cursor;
+ PWCHAR String;
+ DWORD Error;
+ LPWSTR Fields[ MAX_RPL_FIELD + 1]; // add 1 for NULL terminator
+
+ Error = BootCreateTable();
+ if ( Error != ERROR_SUCCESS) {
+ return( Error);
+ }
+
+ Error = ProfileCreateTable();
+ if ( Error != ERROR_SUCCESS) {
+ return( Error);
+ }
+
+ Error = WkstaCreateTable();
+ if ( Error != ERROR_SUCCESS) {
+ return( Error);
+ }
+
+ Error = AdapterCreateTable();
+ if ( Error != ERROR_SUCCESS) {
+ return( Error);
+ }
+
+ String = ReadTextFile( FilePath, RplMapFile, MAX_RPL_MAP_FILE_SIZE);
+ if ( String == NULL) {
+ return( GetLastError());
+ }
+
+ for ( Cursor = GetFirstLine( String);
+ *Cursor != 0;
+ Cursor = GetNextLine( Cursor)) {
+
+ Cursor += OffsetAfterComment( Cursor);
+ switch( RplGetRecordType( Cursor)) {
+ case RecordTypePcDosBoot:
+ NOTHING;
+ break;
+ case RecordTypeBoot: // os/2 lm2.0 & higher, boot block record
+ LineToWords( Cursor, Fields, MAX_RPL_FIELD);
+ ProcessBoot( Fields);
+ break;
+ case RecordTypeProfile:
+ LineToWords( Cursor, Fields, MAX_RPL_FIELD);
+ ProcessProfile( Fields);
+ break;
+ case RecordTypeUniqueAdapter:
+ LineToWords( Cursor, Fields, MAX_RPL_FIELD);
+ ProcessWksta( Fields);
+ break;
+ case RecordTypeWildAdapter:
+ NOTHING;
+ break;
+ case RecordTypeComment:
+ NOTHING;
+ break;
+ default: // unexpected line
+ DbgUserBreakPoint();
+ break;
+ }
+ }
+
+ if ( GlobalFree( String) != NULL) {
+ RplAssert( TRUE, ("GlobalFree: Error=%d", GetLastError()));
+ }
+
+ return( ERROR_SUCCESS);
+}
+
+VOID GlobalInit()
+{
+#ifdef RPL_DEBUG
+ DebugLevel = 0;
+#endif
+ SesId = 0;
+ DbId = 0;
+ JetInstance = 0;
+ BootTableId = 0;
+ ConfigTableId = 0;
+ ProfileTableId = 0;
+ WkstaTableId = 0;
+ AdapterTableId = 0;
+}
+
+
+VOID DbCleanup()
+{
+ if ( VendorTableId != 0) {
+ Call( JetCloseTable( SesId, VendorTableId));
+ }
+ if ( BootTableId != 0) {
+ Call( JetCloseTable( SesId, BootTableId));
+ }
+ if ( ConfigTableId != 0) {
+ Call( JetCloseTable( SesId, ConfigTableId));
+ }
+ if ( ProfileTableId != 0) {
+ Call( JetCloseTable( SesId, ProfileTableId));
+ }
+ if ( WkstaTableId != 0) {
+ Call( JetCloseTable( SesId, WkstaTableId));
+ }
+ if ( AdapterTableId != 0) {
+ Call( JetCloseTable( SesId, AdapterTableId));
+ }
+ if ( DbId != 0) {
+ Call( JetCloseDatabase( SesId, DbId, 0));
+ Call( JetDetachDatabase( SesId, G_ServiceDatabaseA));
+ }
+ if ( SesId != 0)
+ Call( JetEndSession( SesId, 0));
+ if ( JetInstance != 0) {
+ Call( JetTerm2( JetInstance, JET_bitTermComplete));
+ }
+}
+
+
+DWORD SetSystemParameters( VOID)
+{
+ DWORD DirectoryLengthW = sizeof(G_ServiceDirectoryW)/sizeof(WCHAR);
+ DWORD DirectoryLengthA;
+ DWORD Error = RplRegRead( NULL, NULL, NULL, G_ServiceDirectoryW, &DirectoryLengthW );
+ if (Error != NO_ERROR) {
+ return( Error);
+ }
+ if ( !WideCharToMultiByte( CP_OEMCP,
+ 0,
+ G_ServiceDirectoryW,
+ DirectoryLengthW,
+ G_ServiceDatabaseA,
+ sizeof(G_ServiceDatabaseA)/sizeof(CHAR),
+ NULL,
+ NULL ) ) {
+ return( GetLastError() );
+ }
+ DirectoryLengthA = strlen(G_ServiceDatabaseA);
+ if ( DirectoryLengthA + wcslen(RPL_SERVICE_DATABASE_W) > MAX_PATH
+ || DirectoryLengthA + strlen("temp.tmp") > MAX_PATH
+ || DirectoryLengthA + wcslen(RPL_SYSTEM_DATABASE_W) > MAX_PATH) {
+ return( NERR_RplBadRegistry);
+ }
+
+#ifdef __JET500
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramSystemPath, 0, G_ServiceDatabaseA));
+#else
+ strcpy( G_ServiceDatabaseA + DirectoryLengthA, RPL_SYSTEM_DATABASE );
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramSysDbPath, 0, G_ServiceDatabaseA));
+#endif
+
+ strcpy( G_ServiceDatabaseA + DirectoryLengthA, "temp.tmp" );
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramTempPath, 0, G_ServiceDatabaseA));
+
+ strcpy( G_ServiceDatabaseA + DirectoryLengthA, RPL_SERVICE_DATABASE );
+
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramMaxBuffers, 250, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramBfThrshldLowPrcnt, 0, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramBfThrshldHighPrcnt, 100, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramMaxOpenTables, 30, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramMaxOpenTableIndexes, 105, NULL))
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramMaxCursors, 100, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramMaxSessions, 10, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramMaxVerPages, 64, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramMaxTemporaryTables, 5, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramLogFilePath, 0, "."));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramLogBuffers, 41, NULL));
+#ifdef __JET500
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramLogFileSize, 1000, NULL));
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramBaseName, 0, "j50"));
+#else
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramLogFileSectors, 1000, NULL));
+#endif
+ CallM( JetSetSystemParameter( &JetInstance, 0, JET_paramLogFlushThreshold, 10, NULL));
+ return( NO_ERROR);
+}
+
+
+DWORD CheckFile(
+ PWCHAR FilePath,
+ PWCHAR FileName
+ )
+{
+ DWORD Error = NO_ERROR;
+ WCHAR CompleteFilePath[ MAX_PATH+1];
+ PWCHAR UseFilePath = FileName;
+ HANDLE FindHandle;
+ WIN32_FIND_DATA FindData;
+
+ CompleteFilePath[0] = L'\0';
+ if ( FilePath != NULL && lstrlenW(FilePath) > 0) {
+ lstrcpyW( CompleteFilePath, FilePath);
+ if ( CompleteFilePath[ lstrlenW(CompleteFilePath)-1 ] != L'\\') {
+ lstrcatW( CompleteFilePath, L"\\");
+ }
+ if ( FileName != NULL) {
+ lstrcatW( CompleteFilePath, FileName );
+ }
+ UseFilePath = CompleteFilePath;
+ }
+ FindHandle = FindFirstFile( UseFilePath, &FindData);
+ if (FindHandle == INVALID_HANDLE_VALUE) {
+ Error = GetLastError();
+ }
+ else
+ {
+ FindClose( FindHandle );
+ }
+
+ return(Error);
+}
+
+
+DWORD _CRTAPI1 main(
+ int argc,
+ CHAR ** charArgv
+ )
+{
+ DWORD Error;
+ JET_ERR JetError;
+ WCHAR ** argv;
+ PWCHAR SourceFilePath;
+ BOOL SpecificDirectory = FALSE;
+ PWCHAR ThisDirectory = L".\\";
+ BOOL RplsvcMdbExists = FALSE;
+
+ GlobalInit();
+ Error = SetSystemParameters();
+ if ( Error != NO_ERROR) {
+ goto SkipCleanup;
+ }
+
+ // Find files rpl.map and rplmgr.ini
+ argv = CommandLineToArgvW( GetCommandLineW(), &argc);
+ if ( argv != NULL && argc > 1) {
+ SourceFilePath = argv[ 1];
+ SpecificDirectory = TRUE;
+ } else {
+ SourceFilePath = G_ServiceDirectoryW;
+ }
+ if ( (Error = CheckFile(SourceFilePath, RplMapFile)) != NO_ERROR
+ || (Error = CheckFile(SourceFilePath, L"rplmgr.ini")) != NO_ERROR )
+ {
+ if ( (!SpecificDirectory)
+ && (Error = CheckFile(ThisDirectory, RplMapFile)) == NO_ERROR
+ && (Error = CheckFile(ThisDirectory, L"rplmgr.ini")) == NO_ERROR )
+ {
+ SourceFilePath = ThisDirectory;
+ }
+ }
+ if (Error != NO_ERROR) {
+ RplPrintf0( RPLI_CVT_NoMAP_INI);
+ goto SkipCleanup;
+ }
+
+#ifndef __JET500
+ // find file system.mdb
+ if ( (Error = CheckFile(G_ServiceDirectoryW, RPL_SYSTEM_DATABASE_W))
+ != NO_ERROR) {
+ RplPrintf0( RPLI_CVT_NoSystemMdb);
+ goto SkipCleanup;
+ }
+#endif
+
+ // check for file rplsvc.mdb
+ RplsvcMdbExists = ((Error = CheckFile(G_ServiceDirectoryW,
+ RPL_SERVICE_DATABASE_W))
+ == NO_ERROR);
+ if (RplsvcMdbExists) {
+ RplPrintf0( RPLI_CVT_RplsvcMdbExists);
+#ifndef RPL_DEBUG
+ goto SkipCleanup;
+#endif
+ }
+
+ JetError = JetInit( &JetInstance);
+ if ( JetError == JET_errInvalidPath) {
+ RplPrintf0( RPLI_CVT_NoMDB);
+ Error = MapJetError( Error);
+ goto SkipCleanup;
+ } else if ( JetError == JET_errFileNotFound) {
+ RplPrintf0( RPLI_CVT_StopService);
+ Error = MapJetError( Error);
+ goto SkipCleanup;
+ } else if ( JetError < 0) {
+ RplPrintf0( RPLI_CVT_InitError);
+ Error = MapJetError( Error);
+ goto SkipCleanup;
+ }
+ CallJ( JetBeginSession( JetInstance, &SesId, "admin", ""));
+ JetError = JetCreateDatabase( SesId, G_ServiceDatabaseA, NULL, &DbId, JET_bitDbSingleExclusive);
+ if ( JetError == JET_errDatabaseDuplicate) {
+#ifndef RPL_DEBUG
+ RplPrintf0( RPLI_CVT_OldSystemMdb);
+#endif
+ Error = MapJetError( Error);
+#ifdef RPL_DEBUG
+ if (RplsvcMdbExists) {
+ CallJ( JetAttachDatabase( SesId, G_ServiceDatabaseA, 0));
+ CallJ( JetOpenDatabase( SesId, G_ServiceDatabaseA, NULL, &DbId, JET_bitDbExclusive));
+ BootListTable();
+ ConfigListTable();
+ ProfileListTable();
+ WkstaListTable();
+ }
+#endif
+ } else if ( JetError == JET_errSuccess) {
+ Error = VendorCreateTable();
+ if ( Error != ERROR_SUCCESS) {
+ goto cleanup;
+ }
+ Error = ProcessRplMap( SourceFilePath);
+ if ( Error != ERROR_SUCCESS) {
+ goto cleanup;
+ }
+ Error = ProcessRplmgrIni( SourceFilePath);
+ if ( Error != ERROR_SUCCESS) {
+ goto cleanup;
+ }
+ ConfigPruneTable();
+ ProfilePruneTable();
+ WkstaPruneTable();
+ } else {
+ RplAssert( TRUE, ("CreateDatabase: JetError=%d", JetError));
+ Error = MapJetError( JetError);
+ }
+
+cleanup:
+ DbCleanup();
+
+SkipCleanup:
+ if ( Error != NO_ERROR) {
+ RplPrintf0( RPLI_CVT_USAGE);
+ }
+ return( Error);
+}
+
diff --git a/private/net/svcdlls/rpl/convert/sources b/private/net/svcdlls/rpl/convert/sources
new file mode 100644
index 000000000..2c565a1ea
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/sources
@@ -0,0 +1,51 @@
+MAJORCOMP=net
+MINORCOMP=rplcnv
+
+TARGETPATH=obj
+TARGETNAME=rplcnv
+TARGETTYPE=PROGRAM
+NTTARGETFILE0=nlstxt.h msg00001.bin
+
+USE_CRTDLL=1
+
+TARGETLIBS= \
+ ..\lib\obj\*\rpllib.lib \
+ $(BASEDIR)\public\sdk\lib\*\netlib.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\gdi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\comdlg32.lib \
+ $(BASEDIR)\public\sdk\lib\*\samlib.lib \
+ $(BASEDIR)\public\sdk\lib\*\netapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\wsock32.lib \
+ $(BASEDIR)\public\sdk\lib\*\shell32.lib \
+ $(BASEDIR)\public\sdk\lib\*\jet500.lib \
+ $(BASEDIR)\public\sdk\lib\*\ntdll.lib
+
+!IFNDEF DISABLE_NET_UNICODE
+UNICODE=1
+NET_C_DEFINES=-DUNICODE
+!ENDIF
+
+INCLUDES=.;..\inc;..\..\..\inc;..\..\..\api;..\..\..\..\inc;
+WARNING_LEVEL=-W4
+
+MSC_WARNING_LEVEL=/W3 /WX
+
+SOURCES= \
+ rplmain.c \
+ vendor.c \
+ adapter.c \
+ boot.c \
+ config.c \
+ profile.c \
+ wksta.c \
+ library.c \
+ debug.c \
+ convert.rc
+
+
+C_DEFINES= -DINCL_32= -DNT -DRPC_NO_WINDOWS_H -DWIN32 -DRPL_RPLCNV
+
+UMTYPE=console
diff --git a/private/net/svcdlls/rpl/convert/vendor.c b/private/net/svcdlls/rpl/convert/vendor.c
new file mode 100644
index 000000000..7e83f4491
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/vendor.c
@@ -0,0 +1,139 @@
+/*++
+
+Copyright (c) 1987-1994 Microsoft Corporation
+
+Module Name:
+
+ vendor.c
+
+Abstract:
+
+ Creates boot block table (server record table). Parses old style
+ RPL.MAP server records and creates corresponding entries in jet
+ database table.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 16 - March - 1994
+
+Revision History:
+
+--*/
+
+#include "local.h"
+#define RPLVENDOR_ALLOCATE
+#include "vendor.h"
+#undef RPLVENDOR_ALLOCATE
+
+RPL_VENDOR_INFO_0 VendorInfoTable[]
+ = {
+ { L"00001B", L"Novell (NE1000, NE2000)"},
+ { L"00004B", L"Nokia/ICL (EtherTeam 16)"},
+ { L"000062", L"3Com 3Station"},
+ { L"0000C0", L"Western Digital/SMC (Ethernet)"},
+ { L"0000F6", L"Madge Smart Ringnodes"},
+ { L"0020AF", L"3Com (Elnk II, Elnk III, Tokenlink III)"},
+ { L"004033", L"NE2000-compatible"},
+ { L"004095", L"NE2000-compatible"},
+ { L"00608C", L"3Com (Elnk 16, Elnk II, Elnk/MC, Elnk III)"},
+ { L"00AA00", L"Intel (EtherExpress 16, EtherExpress PRO)"},
+ { L"020701", L"Racal Interlan (NI6510, NI5210)"},
+ { L"02608C", L"3Com (3Station, Elnk, Elnk II, Elnk Plus, Elnk/MC)"},
+ { L"080009", L"HP (EtherTwist, AM2100)"},
+ { L"08005A", L"IBM (Token Ring, Ethernet)"},
+ { L"10005A", L"IBM (Token Ring, Ethernet)"},
+ { L"42608C", L"3Com (Tokenlink)"}
+};
+#define VENDOR_INFO_TABLE_LENGTH (sizeof(VendorInfoTable)/sizeof(VendorInfoTable[0]))
+
+
+VOID ProcessVendor(
+ IN PWCHAR VendorName,
+ IN PWCHAR VendorComment
+ )
+{
+ DWORD Flags;
+
+ if ( !ValidHexName( VendorName, RPL_VENDOR_NAME_LENGTH, TRUE)) {
+ RplAssert( TRUE, ("Invalid VendorName = %ws", VendorName));
+ return;
+ }
+
+ Call( JetPrepareUpdate( SesId, VendorTableId, JET_prepInsert));
+
+ Call( JetSetColumn( SesId, VendorTableId,
+ VendorTable[ VENDOR_VendorName].ColumnId, VendorName,
+ (wcslen( VendorName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, VendorTableId,
+ VendorTable[ VENDOR_VendorComment].ColumnId, VendorComment,
+ (wcslen( VendorComment) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Flags = 0;
+ Call( JetSetColumn( SesId, VendorTableId,
+ VendorTable[ VENDOR_Flags].ColumnId, &Flags,
+ sizeof( Flags), 0, NULL));
+
+ Call( JetUpdate( SesId, VendorTableId, NULL, 0, NULL));
+}
+
+
+
+DWORD VendorCreateTable( VOID)
+{
+ JET_COLUMNDEF ColumnDef;
+ JET_ERR JetError;
+ DWORD index;
+ DWORD Offset;
+ CHAR IndexKey[ 255];
+
+ JetError = JetCreateTable( SesId, DbId, VENDOR_TABLE_NAME,
+ VENDOR_TABLE_PAGE_COUNT, VENDOR_TABLE_DENSITY, &VendorTableId);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateTable failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // Create columns. First initalize fields that do not change between
+ // addition of columns.
+ //
+ ColumnDef.cbStruct = sizeof(ColumnDef);
+ ColumnDef.columnid = 0;
+ ColumnDef.wCountry = 1;
+ ColumnDef.langid = 0x0409; // USA english
+ ColumnDef.cp = 1200; // UNICODE codepage
+ ColumnDef.wCollate = 0;
+ ColumnDef.cbMax = 0;
+ ColumnDef.grbit = 0; // variable length binary and text data.
+
+ for ( index = 0; index < VENDOR_TABLE_LENGTH; index++ ) {
+
+ ColumnDef.coltyp = VendorTable[ index].ColumnType;
+
+ JetError = JetAddColumn( SesId, VendorTableId,
+ VendorTable[ index].ColumnName, &ColumnDef,
+ NULL, 0, &VendorTable[ index].ColumnId);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("AddColumn( %s) failed err=%d", VendorTable[ index].ColumnName, JetError));
+ return( MapJetError( JetError));
+ }
+ }
+
+ Offset = AddKey( IndexKey, '+', VendorTable[ VENDOR_VendorName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, VendorTableId, VENDOR_INDEX_VendorName,
+ JET_bitIndexPrimary, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ for ( index = 0; index < VENDOR_INFO_TABLE_LENGTH; index++) {
+ ProcessVendor( VendorInfoTable[ index].VendorName,
+ VendorInfoTable[ index].VendorComment);
+ }
+
+ return( ERROR_SUCCESS);
+}
+
diff --git a/private/net/svcdlls/rpl/convert/wksta.c b/private/net/svcdlls/rpl/convert/wksta.c
new file mode 100644
index 000000000..96e45683a
--- /dev/null
+++ b/private/net/svcdlls/rpl/convert/wksta.c
@@ -0,0 +1,565 @@
+/*++
+
+Copyright (c) 1987-1993 Microsoft Corporation
+
+Module Name:
+
+ wksta.c
+
+Abstract:
+
+ Creates wksta table. Parses old style RPL.MAP unique adapter id
+ workstation records and creates corresponding entries in jet
+ database table.
+
+Author:
+
+ Vladimir Z. Vulovic (vladimv) 19 - November - 1993
+
+Revision History:
+
+--*/
+
+#include "local.h"
+#include "winsock.h" // for inet_addr()
+#define RPLWKSTA_ALLOCATE
+#include "wksta.h"
+#undef RPLWKSTA_ALLOCATE
+
+
+DWORD WkstaCreateTable( VOID)
+{
+ JET_COLUMNDEF ColumnDef;
+ JET_ERR JetError;
+ DWORD index;
+ DWORD Offset;
+ CHAR IndexKey[ 255];
+
+ JetError = JetCreateTable( SesId, DbId, WKSTA_TABLE_NAME,
+ WKSTA_TABLE_PAGE_COUNT, WKSTA_TABLE_DENSITY, &WkstaTableId);
+
+ //
+ // Create columns. First initalize fields that do not change between
+ // addition of columns.
+ //
+ ColumnDef.cbStruct = sizeof(ColumnDef);
+ ColumnDef.columnid = 0;
+ ColumnDef.wCountry = 1;
+ ColumnDef.langid = 0x0409; // USA english
+ ColumnDef.cp = 1200; // UNICODE codepage
+ ColumnDef.wCollate = 0;
+ ColumnDef.cbMax = 0;
+ ColumnDef.grbit = 0; // variable length binary and text data.
+
+ for ( index = 0; index < WKSTA_TABLE_LENGTH; index++) {
+
+ ColumnDef.coltyp = WkstaTable[ index].ColumnType;
+
+ CallM( JetAddColumn( SesId, WkstaTableId,
+ WkstaTable[ index].ColumnName, &ColumnDef,
+ NULL, 0, &WkstaTable[ index].ColumnId));
+ }
+
+ //
+ // For now, the only reason we define these indices is to make sure
+ // wksta records have different AdapterName-s and different WkstaName-s.
+ // BUGBUG We could perhaps do this for TCP/IP address field as well.
+ //
+ Offset = AddKey( IndexKey, '+', WkstaTable[ WKSTA_AdapterName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, WkstaTableId, WKSTA_INDEX_AdapterName,
+ JET_bitIndexPrimary, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ Offset = AddKey( IndexKey, '+', WkstaTable[ WKSTA_WkstaName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, WkstaTableId, WKSTA_INDEX_WkstaName,
+ JET_bitIndexUnique, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // +ProfileName+WkstaName index is used to enumerate all wkstas attached
+ // to a given profile.
+ //
+ Offset = AddKey( IndexKey, '+', WkstaTable[ WKSTA_ProfileName].ColumnName);
+ Offset += AddKey( IndexKey + Offset, '+', WkstaTable[ WKSTA_WkstaName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, WkstaTableId, WKSTA_INDEX_ProfileNameWkstaName,
+ JET_bitIndexUnique, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ //
+ // +BootName+WkstaName index is used to find if a there is a
+ // wksta record for a given boot record.
+ //
+ Offset = AddKey( IndexKey, '+', WkstaTable[ WKSTA_BootName].ColumnName);
+ Offset += AddKey( IndexKey + Offset, '+', WkstaTable[ WKSTA_WkstaName].ColumnName);
+ IndexKey[ Offset++] = '\0';
+ JetError = JetCreateIndex( SesId, WkstaTableId, WKSTA_INDEX_BootNameWkstaName,
+ JET_bitIndexUnique, IndexKey, Offset, 50);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("CreateIndex failed err=%d", JetError));
+ return( MapJetError( JetError));
+ }
+
+ return( ERROR_SUCCESS);
+}
+
+
+DWORD TcpIpAddressToDword( IN PWCHAR UnicodeString)
+{
+ CHAR DbcsString[ 20];
+ DWORD ByteCount;
+
+ if ( *UnicodeString == 0) {
+ //
+ // WideCharToMultiByte() would convert this string successfully,
+ // returning ByteCount equal to 1 and DbcsString[ 0] equal to 0.
+ // And inet_addr() would then return 0, a valid TCP/IP address.
+ //
+ return( INADDR_NONE);
+ }
+ ByteCount = WideCharToMultiByte( // counts the terminating null byte
+ CP_OEMCP, // RonaldM confirms inet_addr() wants OEM string
+ 0,
+ UnicodeString,
+ -1,
+ DbcsString, // dbcs string
+ sizeof( DbcsString),
+ NULL, // no default character
+ NULL // no default character flag
+ );
+ if ( ByteCount == 0) {
+ return( INADDR_NONE); // failed to convert to DBCS
+ }
+ //
+ // Convert the string to network byte order, then to host byte order.
+ //
+ return( (DWORD)ntohl( inet_addr( DbcsString)));
+}
+
+
+VOID ProcessWksta( PWCHAR * Fields)
+/*++
+ We need to get from here whether wksta record is PERSONAL or SHARED.
+--*/
+{
+//
+// Wksta record (computer record) defines.
+//
+#define WKSTA_DISABLED_CH L'D'
+#define WKSTA_ENABLED_CH L'R'
+
+//
+// WKSTA_SERVER_INDEX is an index of a boot block record identifier in a string
+// table corresponding to a wksta record. This index is 0-based. Note
+// that wksta record is parsed so that field ",,," is counted as three
+// entries not as one.
+//
+#define WKSTA_AdapterName_INDEX 0 // wksta adapter id
+#define WKSTA_WKSTANAME_INDEX 1 // wksta name
+#define WKSTA_LOGONINPUT_INDEX 2 // username/password prompting policy
+#define WKSTA_FITFILE_INDEX 3 // fit file name
+#define WKSTA_SHARING_INDEX 5 // shared or personal profile
+#define WKSTA_BOOTNAME_INDEX 13 // boot block identifier
+#define WKSTA_PROFILENAME_INDEX 15 // profile name
+#define WKSTA_COMMENT_INDEX 16 // wksta comment
+#define WKSTA_TCPIPADDRESS_INDEX 17 // wksta tcpip address
+#define WKSTA_TCPIPSUBNET_INDEX 18 // wksta subnet mask
+#define WKSTA_TCPIPGATEWAY_INDEX 19 // wksta tcpip gateway address
+
+ PWCHAR WkstaComment;
+ PWCHAR WkstaName;
+ PWCHAR AdapterName;
+ PWCHAR ProfileName;
+ DWORD TcpIpAddress;
+ DWORD TcpIpSubnet;
+ DWORD TcpIpGateway;
+ PWCHAR Fit;
+ PWCHAR BootName;
+ JET_ERR JetError;
+ DWORD Flags;
+
+ Flags = 0;
+
+ WkstaName = Fields[ WKSTA_WKSTANAME_INDEX];
+ if ( !ValidName( WkstaName, RPL_MAX_WKSTA_NAME_LENGTH, TRUE)) {
+ RplPrintf1( RPLI_CVT_WkstaInvalid, WkstaName);
+ RplAssert( TRUE, ("Bad wksta name"));
+ return;
+ }
+ _wcsupr( WkstaName);
+
+ AdapterName = Fields[ WKSTA_AdapterName_INDEX];
+ if ( !ValidHexName( AdapterName, RPL_ADAPTER_NAME_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_WkstaInvalidAdapter, WkstaName, AdapterName);
+ RplAssert( TRUE, ("Bad adapter id"));
+ return;
+ }
+ _wcsupr( AdapterName);
+
+ if ( Fields[ WKSTA_LOGONINPUT_INDEX] [1] != 0) {
+ RplPrintf2( RPLI_CVT_WkstaInvalidLogon, WkstaName, Fields[ WKSTA_LOGONINPUT_INDEX]);
+ RplAssert( TRUE, ("Bad username/password prompting field."));
+ return;
+ }
+ switch( Fields[ WKSTA_LOGONINPUT_INDEX] [0]) {
+ case WKSTA_LOGON_INPUT_REQUIRED:
+ Flags |= WKSTA_FLAGS_LOGON_INPUT_REQUIRED;
+ break;
+ case WKSTA_LOGON_INPUT_OPTIONAL:
+ Flags |= WKSTA_FLAGS_LOGON_INPUT_OPTIONAL;
+ break;
+ case WKSTA_LOGON_INPUT_IMPOSSIBLE:
+ Flags |= WKSTA_FLAGS_LOGON_INPUT_IMPOSSIBLE;
+ break;
+ default:
+ RplPrintf2( RPLI_CVT_WkstaInvalidLogon, WkstaName, Fields[ WKSTA_LOGONINPUT_INDEX]);
+ RplAssert( TRUE, ("Bad username/password prompting field."));
+ return;
+ break;
+ }
+
+ Fit = AddFileExtension( Fields[ WKSTA_FITFILE_INDEX], L".FIT", TRUE);
+ if ( !ValidName( Fit, RPL_MAX_STRING_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_WkstaInvalidFit, WkstaName, Fields[ WKSTA_FITFILE_INDEX]);
+ RplAssert( TRUE, ("Bad fit file field %ws.", Fields[ WKSTA_FITFILE_INDEX]));
+ return;
+ }
+
+ //
+ // Find if wksta record is enabled or disabled.
+ //
+ switch( Fields[ WKSTA_SHARING_INDEX] [0]) {
+ case WKSTA_SHARING_TRUE:
+ Flags |= WKSTA_FLAGS_SHARING_TRUE;
+ break;
+ case WKSTA_SHARING_FALSE:
+ Flags |= WKSTA_FLAGS_SHARING_FALSE;
+ break;
+ default:
+ RplPrintf2( RPLI_CVT_WkstaInvalidSharing, WkstaName, Fields[ WKSTA_SHARING_INDEX]);
+ RplAssert( TRUE, ("Data sharing not properly set."));
+ return;
+ break;
+ }
+
+ //
+ // Find if wksta record is enabled or disabled.
+ //
+ switch( *Fields[ WKSTA_BOOTNAME_INDEX]) {
+ case WKSTA_ENABLED_CH:
+ break;
+ case WKSTA_DISABLED_CH:
+ RplPrintf2( RPLI_CVT_WkstaDisabledBoot, WkstaName, Fields[ WKSTA_BOOTNAME_INDEX]);
+ return;
+ break;
+ default:
+ RplPrintf2( RPLI_CVT_WkstaInvalidBoot, WkstaName, Fields[ WKSTA_BOOTNAME_INDEX]);
+ RplAssert( TRUE, ("Bad switch"));
+ return;
+ break;
+ }
+
+ BootName = Fields[ WKSTA_BOOTNAME_INDEX] + 1; // skip leading char
+ if ( !ValidName( BootName, RPL_MAX_STRING_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_WkstaInvalidBoot, WkstaName, Fields[ WKSTA_BOOTNAME_INDEX]);
+ RplAssert( TRUE, ("Bad boot name"));
+ return;
+ }
+
+ ProfileName = Fields[ WKSTA_PROFILENAME_INDEX];
+ if ( !ValidName( ProfileName, RPL_MAX_PROFILE_NAME_LENGTH, TRUE)) {
+ RplPrintf2( RPLI_CVT_WkstaInvalidProfile, WkstaName, ProfileName);
+ RplAssert( TRUE, ("Bad profile name"));
+ return;
+ }
+ _wcsupr( ProfileName);
+
+ WkstaComment = Fields[ WKSTA_COMMENT_INDEX];
+ if ( RPL_STRING_TOO_LONG( WkstaComment)) {
+ WkstaComment[ RPL_MAX_STRING_LENGTH] = 0; // silently truncate it
+ }
+
+ TcpIpAddress = TcpIpAddressToDword( Fields[ WKSTA_TCPIPADDRESS_INDEX]);
+ TcpIpSubnet = TcpIpAddressToDword( Fields[ WKSTA_TCPIPSUBNET_INDEX]);
+ TcpIpGateway = TcpIpAddressToDword( Fields[ WKSTA_TCPIPGATEWAY_INDEX]);
+
+ //
+ // If all addresses are valid assumes this (old style) client does not
+ // want DHCP to be enabled. In other words, if any addresses is bogus
+ // this client does not loose anything by trying out DHCP.
+ //
+ if ( TcpIpAddress != INADDR_NONE && TcpIpSubnet != INADDR_NONE
+ && TcpIpGateway != -1) {
+ Flags |= WKSTA_FLAGS_DHCP_FALSE;
+ } else {
+ Flags |= WKSTA_FLAGS_DHCP_TRUE;
+ }
+
+ //
+ // Play it safe; assume user accounts are not to be deleted
+ //
+ Flags |= WKSTA_FLAGS_DELETE_FALSE;
+
+ Call( JetPrepareUpdate( SesId, WkstaTableId, JET_prepInsert));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_WkstaName].ColumnId, WkstaName,
+ (wcslen( WkstaName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_WkstaComment].ColumnId, WkstaComment,
+ (wcslen( WkstaComment) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_ProfileName].ColumnId, ProfileName,
+ (wcslen( ProfileName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_BootName].ColumnId, BootName,
+ (wcslen( BootName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_FitFile].ColumnId, Fit,
+ (wcslen( Fit) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_AdapterName].ColumnId, AdapterName,
+ (wcslen( AdapterName) + 1) * sizeof(WCHAR), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_TcpIpAddress].ColumnId, &TcpIpAddress,
+ sizeof( TcpIpAddress), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_TcpIpSubnet].ColumnId, &TcpIpSubnet,
+ sizeof( TcpIpSubnet), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_TcpIpGateway].ColumnId, &TcpIpGateway,
+ sizeof( TcpIpGateway), 0, NULL));
+
+ Call( JetSetColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_Flags].ColumnId, &Flags,
+ sizeof( Flags), 0, NULL));
+
+ JetError = JetUpdate( SesId, WkstaTableId, NULL, 0, NULL);
+ if ( JetError == JET_errKeyDuplicate) {
+ RplPrintf2( RPLI_CVT_WkstaDuplicateName, WkstaName, AdapterName);
+ } else if (JetError != JET_errSuccess) {
+ RplAssert( TRUE,("JetUpdate failed error = %d", JetError));
+ }
+}
+
+
+VOID WkstaPruneTable( VOID)
+/*++
+ Eliminate wksta records that do not have a corresponding profile record
+ defined or do not have a corresponding server record defined.
+--*/
+{
+
+ WCHAR Name[ 20]; // BUGBUG arbitrary size
+ DWORD NameSize;
+ JET_ERR ForJetError;
+ JET_ERR JetError;
+
+ for ( ForJetError = JetMove( SesId, WkstaTableId, JET_MoveFirst, 0);
+ ForJetError == JET_errSuccess;
+ ForJetError = JetMove( SesId, WkstaTableId, JET_MoveNext, 0)) {
+
+ JetError = JetRetrieveColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_BootName].ColumnId, Name,
+ sizeof( Name), &NameSize, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
+ Call( JetDelete( SesId, WkstaTableId));
+ continue;
+ }
+ if ( !FindBoot( Name)) {
+ RplAssert( TRUE, ("FindBoot failed."));
+ Call( JetDelete( SesId, WkstaTableId));
+ continue;
+ }
+
+ JetError = JetRetrieveColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_ProfileName].ColumnId, Name,
+ sizeof( Name), &NameSize, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
+ Call( JetDelete( SesId, WkstaTableId));
+ continue;
+ }
+ //
+ // This will eliminate workstations joined to the DEFAULT profile
+ // since the DEFAULT profile does not have its profile record in
+ // RPL.MAP. Note that default boot is not supported under NT.
+ // Instead of just deleting these workstations, we could also
+ // add the corresponding AdapterName record to the AdapterName table.
+ // This may not be worth the effort though.
+ //
+ if ( !FindProfile( Name)) {
+ if ( _wcsicmp( Name, L"DEFAULT") == 0) {
+ JetError = JetRetrieveColumn( SesId, WkstaTableId,
+ WkstaTable[ WKSTA_WkstaName].ColumnId, Name,
+ sizeof( Name), &NameSize, 0, NULL);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("RetriveColumn failed err=%d", JetError));
+ } else {
+ RplPrintf1( RPLI_CVT_WkstaDefaultProfile, Name);
+ }
+ } else {
+ RplAssert( TRUE, ("FindProfile failed."));
+ }
+ Call( JetDelete( SesId, WkstaTableId));
+ continue;
+ }
+ }
+
+ //
+ // The error below is the only expected error (end of table error).
+ //
+ if ( ForJetError != JET_errNoCurrentRecord) {
+ RplAssert( TRUE, ("ForJetError = %d", ForJetError));
+ }
+}
+
+
+VOID WkstaListTable( VOID)
+{
+ ListTable( WKSTA_TABLE_NAME, WkstaTable[ WKSTA_AdapterName].ColumnName,
+ WKSTA_INDEX_WkstaName);
+}
+
+
+
+BOOL RplDbInitTable( IN PCHAR TableName, IN OUT PRPL_COLUMN_INFO Table,
+ IN DWORD TableLength, IN OUT JET_TABLEID * pTableId)
+{
+ JET_COLUMNDEF ColumnDef;
+ DWORD index;
+
+ CallB( JetOpenTable( SesId, DbId, TableName, NULL, 0,
+ JET_bitTableDenyWrite, pTableId));
+
+ for ( index = 0; index < TableLength; index++) {
+ CallB( JetGetTableColumnInfo( SesId, *pTableId, Table[ index].ColumnName,
+ &ColumnDef, sizeof( ColumnDef), JET_ColInfo));
+ Table[ index].ColumnId = ColumnDef.columnid;
+ Table[ index].ColumnType = ColumnDef.coltyp;
+ }
+ return( TRUE);
+}
+
+
+BOOL FindWksta( IN LPWSTR AdapterName)
+/*++
+ Return TRUE if it finds wksta record for input AdapterName.
+ Returns FALSE otherwise.
+
+ BUGBUG This code is inefficient. I should really make AdapterName a
+ jet currency data, but even now it is kind of stupid taking wcslen of
+ AdapterName since it is a fixed length string.
+--*/
+{
+ JET_ERR JetError;
+
+ JetError = JetSetCurrentIndex( SesId, WkstaTableId, WKSTA_INDEX_AdapterName);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("SetCurrentIndex failed err=%d", JetError));
+ return( FALSE);
+ }
+ JetError = JetMakeKey( SesId, WkstaTableId, AdapterName,
+ ( wcslen( AdapterName) + 1) * sizeof(WCHAR), JET_bitNewKey);
+ if ( JetError != JET_errSuccess) {
+ RplAssert( TRUE, ("MakeKey failed err=%d", JetError));
+ return( FALSE);
+ }
+ JetError = JetSeek( SesId, WkstaTableId, JET_bitSeekEQ);
+ if ( JetError != JET_errSuccess) {
+ if ( JetError == JET_errRecordNotFound) {
+ //
+ // This is an expected error, do not break for this.
+ //
+ RplAssert( TRUE, ( "FindWksta( %ws) failed", AdapterName));
+ } else {
+ RplAssert( TRUE, ("JetSeek failed err=%d", JetError));
+ }
+ return( FALSE);
+ }
+ return( TRUE);
+}
+
+#ifdef NOT_YET
+
+VOID Display( IN DWORD index)
+{
+ BYTE Buffer[ 120];
+ DWORD DataSize;
+ DWORD AddressDword;
+
+ Call( JetRetrieveColumn( SesId, WkstaTableId,
+ WkstaTable[ index].ColumnId, Buffer,
+ sizeof( Buffer), &DataSize, 0, NULL));
+
+ RplDbgPrint(( "%s = ", WkstaTable[ index].ColumnName));
+
+ switch( index) {
+ case WKSTA_WkstaName:
+ case WKSTA_WkstaComment:
+ case WKSTA_ProfileName:
+ case WKSTA_FitFile:
+ case WKSTA_BootName:
+ RplDbgPrint(( "%ws\n", Buffer));
+ break;
+ case WKSTA_TcpIpAddress:
+ case WKSTA_TcpIpSubnet:
+ case WKSTA_TcpIpGateway:
+ AddressDword = *(PDWORD)Buffer;
+ FillTcpIpString( Buffer, AddressDword);
+ RplDbgPrint(( "%s\n", Buffer));
+ break;
+ case WKSTA_Flags:
+ RplDbgPrint(( "0x%x\n", *(PDWORD)Buffer));
+ break;
+ }
+}
+
+
+BOOL ListWkstaInfo( IN PWCHAR AdapterName)
+/*++
+ Returns TRUE if it can find all the information needed to boot the client.
+ Returns FALSE otherwise.
+--*/
+{
+ if ( !RplDbInitTable( WKSTA_TABLE_NAME, WkstaTable, WKSTA_TABLE_LENGTH,
+ &WkstaTableId)) {
+ return( FALSE);
+ }
+ if ( !FindWksta( AdapterName)) {
+ RplAssert( TRUE, ("FindWksta( %ws) failed", AdapterName));
+ return( FALSE);
+ }
+ Display( WKSTA_WkstaName);
+ Display( WKSTA_WkstaComment);
+ Display( WKSTA_Flags);
+ Display( WKSTA_ProfileName);
+ Display( WKSTA_FitFile);
+ Display( WKSTA_BootName);
+ Display( WKSTA_TcpIpAddress);
+ Display( WKSTA_TcpIpSubnet);
+ Display( WKSTA_TcpIpGateway);
+ return( TRUE);
+}
+#endif
+