summaryrefslogtreecommitdiffstats
path: root/private/nw/install
diff options
context:
space:
mode:
authorAdam <you@example.com>2020-05-17 05:51:50 +0200
committerAdam <you@example.com>2020-05-17 05:51:50 +0200
commite611b132f9b8abe35b362e5870b74bce94a1e58e (patch)
treea5781d2ec0e085eeca33cf350cf878f2efea6fe5 /private/nw/install
downloadNT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.gz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.bz2
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.lz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.xz
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.tar.zst
NT4.0-e611b132f9b8abe35b362e5870b74bce94a1e58e.zip
Diffstat (limited to '')
-rw-r--r--private/nw/install/dirs25
-rw-r--r--private/nw/install/setupdll/common.h122
-rw-r--r--private/nw/install/setupdll/dllinit.c65
-rw-r--r--private/nw/install/setupdll/lodctr.c1531
-rw-r--r--private/nw/install/setupdll/makefile10
-rw-r--r--private/nw/install/setupdll/nwcfg.cxx318
-rw-r--r--private/nw/install/setupdll/nwcfg.def19
-rw-r--r--private/nw/install/setupdll/nwcfg.h22
-rw-r--r--private/nw/install/setupdll/nwcfg.hxx28
-rw-r--r--private/nw/install/setupdll/nwcfg.prf1
-rw-r--r--private/nw/install/setupdll/nwcfg.rc20
-rw-r--r--private/nw/install/setupdll/removesz.c58
-rw-r--r--private/nw/install/setupdll/rules.mk4
-rw-r--r--private/nw/install/setupdll/setvalue.c696
-rw-r--r--private/nw/install/setupdll/sources48
-rw-r--r--private/nw/install/setupdll/unlodctr.c1006
-rw-r--r--private/nw/install/wksta/alpha.txt3
-rw-r--r--private/nw/install/wksta/eng.txt55
-rw-r--r--private/nw/install/wksta/files10.txt94
-rw-r--r--private/nw/install/wksta/files10a.txt37
-rw-r--r--private/nw/install/wksta/i386.txt3
-rw-r--r--private/nw/install/wksta/makefile1
-rw-r--r--private/nw/install/wksta/makefile.inc29
-rw-r--r--private/nw/install/wksta/mips.txt3
-rw-r--r--private/nw/install/wksta/nw.inf1224
-rw-r--r--private/nw/install/wksta/nwperf.ini37
-rw-r--r--private/nw/install/wksta/nwperfm.h24
-rw-r--r--private/nw/install/wksta/ppc.txt4
-rw-r--r--private/nw/install/wksta/sources42
29 files changed, 5529 insertions, 0 deletions
diff --git a/private/nw/install/dirs b/private/nw/install/dirs
new file mode 100644
index 000000000..b77c0323f
--- /dev/null
+++ b/private/nw/install/dirs
@@ -0,0 +1,25 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ dirs.
+
+Abstract:
+
+ This file specifies the subdirectories of the current directory that
+ contain component makefiles.
+
+
+Author:
+
+ Steve Wood (stevewo) 17-Apr-1990
+
+NOTE: Commented description of this file is in \nt\bak\bin\dirs.tpl
+
+!ENDIF
+
+DIRS=setupdll
+
+OPTIONAL_DIRS=
diff --git a/private/nw/install/setupdll/common.h b/private/nw/install/setupdll/common.h
new file mode 100644
index 000000000..c04595aa3
--- /dev/null
+++ b/private/nw/install/setupdll/common.h
@@ -0,0 +1,122 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+common.h
+
+ constants and globals that are common to LODCTR and UNLODCTR
+
+Author:
+
+ Bob Watson (a-robw) 10 Feb 93
+
+Revision History:
+
+--*/
+#ifndef _LODCTR_COMMON_H_
+#define _LODCTR_COMMON_H_
+//
+// Local constants
+//
+#define RESERVED 0L
+#define LARGE_BUFFER_SIZE 0x10000 // 64K
+#define MEDIUM_BUFFER_SIZE 0x8000 // 32K
+#define SMALL_BUFFER_SIZE 0x1000 // 4K
+#define FILE_NAME_BUFFER_SIZE MAX_PATH
+#define DISP_BUFF_SIZE 256L
+#define SIZE_OF_OFFSET_STRING 15
+//
+// Data structure and type definitions
+//
+typedef struct _NAME_ENTRY {
+ struct _NAME_ENTRY *pNext;
+ DWORD dwOffset;
+ DWORD dwType;
+ LPTSTR lpText;
+} NAME_ENTRY, *PNAME_ENTRY;
+
+typedef struct _LANGUAGE_LIST_ELEMENT {
+ struct _LANGUAGE_LIST_ELEMENT *pNextLang; // next lang. list
+ LPTSTR LangId; // lang ID string for this elem
+ PNAME_ENTRY pFirstName; // head of name list
+ PNAME_ENTRY pThisName; // pointer to current entry
+ DWORD dwNumElements; // number of elements in array
+ DWORD dwNameBuffSize;
+ DWORD dwHelpBuffSize;
+ PBYTE NameBuffer; // buffer to store strings
+ PBYTE HelpBuffer; // buffer to store help strings
+} LANGUAGE_LIST_ELEMENT, *PLANGUAGE_LIST_ELEMENT;
+
+typedef struct _SYMBOL_TABLE_ENTRY {
+ struct _SYMBOL_TABLE_ENTRY *pNext;
+ LPTSTR SymbolName;
+ DWORD Value;
+} SYMBOL_TABLE_ENTRY, *PSYMBOL_TABLE_ENTRY;
+//
+// Utility Routine prototypes for routines in common.c
+//
+#define StringToInt(in,out) \
+ (((_stscanf ((in), TEXT(" %d"), (out))) == 1) ? TRUE : FALSE)
+
+
+#if _INITIALIZE_GLOBALS_
+//
+//
+// Text string Constant definitions
+//
+const LPTSTR NamesKey = TEXT("SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Perflib");
+const LPTSTR DefaultLangId = TEXT("009");
+const LPTSTR Counters = TEXT("Counters");
+const LPTSTR Help = TEXT("Help");
+const LPTSTR VersionStr = TEXT("Version");
+const LPTSTR LastHelp = TEXT("Last Help");
+const LPTSTR LastCounter = TEXT("Last Counter");
+const LPTSTR FirstHelp = TEXT("First Help");
+const LPTSTR FirstCounter = TEXT("First Counter");
+const LPTSTR Busy = TEXT("Updating");
+const LPTSTR Slash = TEXT("\\");
+const LPTSTR BlankString = TEXT(" ");
+const LPSTR BlankAnsiString = " ";
+const LPTSTR DriverPathRoot = TEXT("SYSTEM\\CurrentControlSet\\Services");
+const LPTSTR Performance = TEXT("Performance");
+const LPTSTR CounterNameStr = TEXT("Counter ");
+const LPTSTR HelpNameStr = TEXT("Explain ");
+const LPTSTR AddCounterNameStr = TEXT("Addcounter ");
+const LPTSTR AddHelpNameStr = TEXT("Addexplain ");
+
+//
+// Global Buffers
+//
+TCHAR DisplayStringBuffer[DISP_BUFF_SIZE];
+CHAR TextFormat[DISP_BUFF_SIZE];
+HANDLE hMod = NULL; // process handle
+DWORD dwLastError = ERROR_SUCCESS;
+
+#else // just declare the globals
+
+extern const LPTSTR NamesKey;
+extern const LPTSTR VersionStr;
+extern const LPTSTR DefaultLangId;
+extern const LPTSTR Counters;
+extern const LPTSTR Help;
+extern const LPTSTR LastHelp;
+extern const LPTSTR LastCounter;
+extern const LPTSTR FirstHelp;
+extern const LPTSTR FirstCounter;
+extern const LPTSTR Busy;
+extern const LPTSTR Slash;
+extern const LPTSTR BlankString;
+extern const LPSTR BlankAnsiString;
+extern const LPTSTR DriverPathRoot;
+extern const LPTSTR Performance;
+//
+// Global Buffers
+//
+extern TCHAR DisplayStringBuffer[DISP_BUFF_SIZE];
+extern CHAR TextFormat[DISP_BUFF_SIZE];
+extern HANDLE hMod;
+extern DWORD dwLastError;
+
+#endif // _INITIALIZE_GLOBALS_
+
+#endif // _LODCTR_COMMON_H_
diff --git a/private/nw/install/setupdll/dllinit.c b/private/nw/install/setupdll/dllinit.c
new file mode 100644
index 000000000..ea326b220
--- /dev/null
+++ b/private/nw/install/setupdll/dllinit.c
@@ -0,0 +1,65 @@
+/*++
+
+Copyright (c) 1990 Microsoft Corporation
+
+Module Name:
+
+ dllinit.c
+
+Abstract:
+
+ This module contians the DLL attach/detach event entry point for
+ a Setup support DLL.
+
+Author:
+
+ Ted Miller (tedm) July-1990
+
+Revision History:
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+
+HINSTANCE ThisDLLHandle;
+
+BOOL
+DLLInit(
+ IN HINSTANCE DLLHandle,
+ IN DWORD Reason,
+ IN LPVOID ReservedAndUnused
+ )
+{
+ ReservedAndUnused;
+
+ switch(Reason) {
+
+ case DLL_PROCESS_ATTACH:
+
+ ThisDLLHandle = DLLHandle;
+ break;
+
+ case DLL_PROCESS_DETACH:
+
+ // Delete all automatically established connections
+ // See UNC handling in netcon.c.
+ //
+ // BUGBUG: This doesn't work, because the unload sequence
+ // is different for "lazy" load DLLs than for load-time DLLs.
+ // INFs must be responsible for calling DeleteAllConnections().
+ //
+ // DeleteAllConnectionsWorker() ;
+ //
+ break ;
+
+ case DLL_THREAD_ATTACH:
+ case DLL_THREAD_DETACH:
+
+ break;
+ }
+
+ return(TRUE);
+}
diff --git a/private/nw/install/setupdll/lodctr.c b/private/nw/install/setupdll/lodctr.c
new file mode 100644
index 000000000..bfe95538d
--- /dev/null
+++ b/private/nw/install/setupdll/lodctr.c
@@ -0,0 +1,1531 @@
+/*++
+
+Copyright (c) 1991 Microsoft Corporation
+
+Module Name:
+
+ lodctr.c
+
+Abstract:
+
+ Program to read the contents of the file specified in the command line
+ and update the registry accordingly
+
+Author:
+
+ Bob Watson (a-robw) 10 Feb 93
+
+Revision History:
+
+ a-robw 25-Feb-93 revised calls to make it compile as a UNICODE or
+ an ANSI app.
+
+--*/
+#define UNICODE 1
+#define _UNICODE 1
+//
+// "C" Include files
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+//
+// Windows Include files
+//
+#include <windows.h>
+#include <winperf.h>
+#include <tchar.h>
+//
+#define _INITIALIZE_GLOBALS_ 1
+#include "common.h"
+#undef _INITIALIZE_GLOBALS_
+
+#define TYPE_HELP 1
+#define TYPE_NAME 2
+
+#include "nwcfg.hxx"
+
+#define OLD_VERSION 0x010000
+DWORD dwSystemVersion;
+
+
+BOOL
+GetDriverName (
+ IN LPTSTR lpIniFile,
+ OUT LPTSTR *lpDevName
+)
+/*++
+GetDriverName
+
+ looks up driver name in the .ini file and returns it in lpDevName
+
+Arguments
+
+ lpIniFile
+
+ Filename of ini file
+
+ lpDevName
+
+ pointer to pointer to reciev buffer w/dev name in it
+
+Return Value
+
+ TRUE if found
+ FALSE if not found in .ini file
+
+--*/
+{
+ DWORD dwRetSize;
+
+ if (lpDevName) {
+ dwRetSize = GetPrivateProfileString (
+ TEXT("info"), // info section
+ TEXT("drivername"), // driver name value
+ TEXT("drivernameNotFound"), // default value
+ *lpDevName,
+ DISP_BUFF_SIZE,
+ lpIniFile);
+
+ if ((lstrcmpi(*lpDevName, TEXT("drivernameNotFound"))) != 0) {
+ // name found
+ return TRUE;
+ } else {
+ // name not found, default returned so return NULL string
+ *lpDevName = TEXT("\0");
+ return FALSE;
+ }
+ } else {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+}
+
+BOOL
+BuildLanguageTables (
+ IN LPTSTR lpIniFile,
+ IN OUT PLANGUAGE_LIST_ELEMENT pFirstElem
+)
+/*++
+
+BuildLanguageTables
+
+ Creates a list of structures that will hold the text for
+ each supported language
+
+Arguments
+
+ lpIniFile
+
+ Filename with data
+
+ pFirstElem
+
+ pointer to first list entry
+
+ReturnValue
+
+ TRUE if all OK
+ FALSE if not
+
+--*/
+{
+
+ LPTSTR lpEnumeratedLangs;
+ LPTSTR lpThisLang;
+
+ PLANGUAGE_LIST_ELEMENT pThisElem;
+
+ DWORD dwSize;
+
+ lpEnumeratedLangs = malloc(SMALL_BUFFER_SIZE);
+
+ if (!lpEnumeratedLangs) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ dwSize = GetPrivateProfileString (
+ TEXT("languages"),
+ NULL, // return all values in multi-sz string
+ TEXT("009"), // english as the default
+ lpEnumeratedLangs,
+ SMALL_BUFFER_SIZE,
+ lpIniFile);
+
+ // do first language
+
+ lpThisLang = lpEnumeratedLangs;
+ pThisElem = pFirstElem;
+
+ while (*lpThisLang) {
+ pThisElem->pNextLang = NULL;
+ pThisElem->LangId = (LPTSTR) malloc ((lstrlen(lpThisLang) + 1) * sizeof(TCHAR));
+ lstrcpy (pThisElem->LangId, lpThisLang);
+ pThisElem->pFirstName = NULL;
+ pThisElem->pThisName = NULL;
+ pThisElem->dwNumElements=0;
+ pThisElem->NameBuffer = NULL;
+ pThisElem->HelpBuffer = NULL;
+
+ // go to next string
+
+ lpThisLang += lstrlen(lpThisLang) + 1;
+
+ if (*lpThisLang) { // there's another so allocate a new element
+ pThisElem->pNextLang = malloc (sizeof(LANGUAGE_LIST_ELEMENT));
+ if (!pThisElem) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+ pThisElem = pThisElem->pNextLang; // point to new one
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL
+LoadIncludeFile (
+ IN LPTSTR lpIniFile,
+ OUT PSYMBOL_TABLE_ENTRY *pTable
+)
+/*++
+
+LoadIncludeFile
+
+ Reads the include file that contains symbolic name definitions and
+ loads a table with the values defined
+
+Arguments
+
+ lpIniFile
+
+ Ini file with include file name
+
+ pTable
+
+ address of pointer to table structure created
+Return Value
+
+ TRUE if table read or if no table defined
+ FALSE if error encountere reading table
+
+--*/
+{
+ INT iNumArgs;
+
+ DWORD dwSize;
+
+ BOOL bReUse;
+
+ PSYMBOL_TABLE_ENTRY pThisSymbol;
+
+ LPTSTR lpIncludeFileName;
+ LPSTR lpIncludeFile;
+ LPSTR lpLineBuffer;
+ LPSTR lpAnsiSymbol;
+
+ FILE *fIncludeFile;
+ HFILE hIncludeFile;
+ OFSTRUCT ofIncludeFile;
+
+ lpIncludeFileName = malloc (MAX_PATH * sizeof (TCHAR));
+ lpIncludeFile = malloc (MAX_PATH);
+ lpLineBuffer = malloc (DISP_BUFF_SIZE);
+ lpAnsiSymbol = malloc (DISP_BUFF_SIZE);
+
+ if (!lpIncludeFileName || !lpLineBuffer || !lpAnsiSymbol) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ // get name of include file (if present)
+
+ dwSize = GetPrivateProfileString (
+ TEXT("info"),
+ TEXT("symbolfile"),
+ TEXT("SymbolFileNotFound"),
+ lpIncludeFileName,
+ _msize(lpIncludeFileName),
+ lpIniFile);
+
+ if ((lstrcmpi(lpIncludeFileName, TEXT("SymbolFileNotFound"))) == 0) {
+ // no symbol file defined
+ *pTable = NULL;
+ return TRUE;
+ }
+
+ // if here, then a symbol file was defined and is now stored in
+ // lpIncludeFileName
+
+ CharToOem (lpIncludeFileName, lpIncludeFile);
+
+ hIncludeFile = OpenFile (
+ lpIncludeFile,
+ &ofIncludeFile,
+ OF_PARSE);
+
+ if (hIncludeFile == HFILE_ERROR) { // unable to read include filename
+ // error is already in GetLastError
+ *pTable = NULL;
+ return FALSE;
+ } else {
+ // open a stream
+ fIncludeFile = fopen (ofIncludeFile.szPathName, "rt");
+
+ if (!fIncludeFile) {
+ *pTable = NULL;
+ return FALSE;
+ }
+ }
+
+ //
+ // read ANSI Characters from include file
+ //
+
+ bReUse = FALSE;
+
+ while (fgets(lpLineBuffer, DISP_BUFF_SIZE, fIncludeFile) != NULL) {
+ if (strlen(lpLineBuffer) > 8) {
+ if (!bReUse) {
+ if (*pTable) {
+ // then add to list
+ pThisSymbol->pNext = malloc (sizeof (SYMBOL_TABLE_ENTRY));
+ pThisSymbol = pThisSymbol->pNext;
+ } else { // allocate first element
+ *pTable = malloc (sizeof (SYMBOL_TABLE_ENTRY));
+ pThisSymbol = *pTable;
+ }
+
+ if (!pThisSymbol) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ // allocate room for the symbol name by using the line length
+ // - the size of "#define "
+
+// pThisSymbol->SymbolName = malloc ((strlen(lpLineBuffer) - 8) * sizeof (TCHAR));
+ pThisSymbol->SymbolName = malloc (DISP_BUFF_SIZE * sizeof (TCHAR));
+
+ if (!pThisSymbol->SymbolName) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ }
+
+ // all the memory is allocated so load the fields
+
+ pThisSymbol->pNext = NULL;
+
+ iNumArgs = sscanf (lpLineBuffer, "#define %s %d",
+ lpAnsiSymbol, &pThisSymbol->Value);
+
+ if (iNumArgs != 2) {
+ *(pThisSymbol->SymbolName) = TEXT('\0');
+ pThisSymbol->Value = (DWORD)-1L;
+ bReUse = TRUE;
+ } else {
+ OemToChar (lpAnsiSymbol, pThisSymbol->SymbolName);
+ bReUse = FALSE;
+ }
+ }
+ }
+
+ if (lpIncludeFileName) free (lpIncludeFileName);
+ if (lpIncludeFile) free (lpIncludeFile);
+ if (lpLineBuffer) free (lpLineBuffer);
+
+ fclose (fIncludeFile);
+
+ return TRUE;
+
+}
+
+BOOL
+ParseTextId (
+ IN LPTSTR lpTextId,
+ IN PSYMBOL_TABLE_ENTRY pFirstSymbol,
+ OUT PDWORD pdwOffset,
+ OUT LPTSTR *lpLangId,
+ OUT PDWORD pdwType
+)
+/*++
+
+ParseTextId
+
+ decodes Text Id key from .INI file
+
+ syntax for this process is:
+
+ {<DecimalNumber>} {"NAME"}
+ {<SymbolInTable>}_<LangIdString>_{"HELP"}
+
+ e.g. 0_009_NAME
+ OBJECT_1_009_HELP
+
+Arguments
+
+ lpTextId
+
+ string to decode
+
+ pFirstSymbol
+
+ pointer to first entry in symbol table (NULL if no table)
+
+ pdwOffset
+
+ address of DWORD to recive offest value
+
+ lpLangId
+
+ address of pointer to Language Id string
+ (NOTE: this will point into the string lpTextID which will be
+ modified by this routine)
+
+ pdwType
+
+ pointer to dword that will recieve the type of string i.e.
+ HELP or NAME
+
+Return Value
+
+ TRUE text Id decoded successfully
+ FALSE unable to decode string
+
+ NOTE: the string in lpTextID will be modified by this procedure
+
+--*/
+{
+ LPTSTR lpThisChar;
+ PSYMBOL_TABLE_ENTRY pThisSymbol;
+
+ // check for valid return arguments
+
+ if (!(pdwOffset) ||
+ !(lpLangId) ||
+ !(pdwType)) {
+ SetLastError (ERROR_INVALID_PARAMETER);
+ return FALSE;
+ }
+
+ // search string from right to left in order to identify the
+ // components of the string.
+
+ lpThisChar = lpTextId + lstrlen(lpTextId); // point to end of string
+
+ while (*lpThisChar != TEXT('_')) {
+ lpThisChar--;
+ if (lpThisChar <= lpTextId) {
+ // underscore not found in string
+ SetLastError (ERROR_INVALID_DATA);
+ return FALSE;
+ }
+ }
+
+ // first underscore found
+
+ if ((lstrcmpi(lpThisChar, TEXT("_NAME"))) == 0) {
+ // name found, so set type
+ *pdwType = TYPE_NAME;
+ } else if ((lstrcmpi(lpThisChar, TEXT("_HELP"))) == 0) {
+ // help text found, so set type
+ *pdwType = TYPE_HELP;
+ } else {
+ // bad format
+ SetLastError (ERROR_INVALID_DATA);
+ return FALSE;
+ }
+
+ // set the current underscore to \0 and look for language ID
+
+ *lpThisChar-- = TEXT('\0');
+
+ while (*lpThisChar != TEXT('_')) {
+ lpThisChar--;
+ if (lpThisChar <= lpTextId) {
+ // underscore not found in string
+ SetLastError (ERROR_INVALID_DATA);
+ return FALSE;
+ }
+ }
+
+ // set lang ID string pointer to current char ('_') + 1
+
+ *lpLangId = lpThisChar + 1;
+
+ // set this underscore to a NULL and try to decode the remaining text
+
+ *lpThisChar = TEXT('\0');
+
+ // see if the first part of the string is a decimal digit
+
+ if ((_stscanf (lpTextId, TEXT(" %d"), pdwOffset)) != 1) {
+ // it's not a digit, so try to decode it as a symbol in the
+ // loaded symbol table
+
+ for (pThisSymbol=pFirstSymbol;
+ pThisSymbol && *(pThisSymbol->SymbolName);
+ pThisSymbol = pThisSymbol->pNext) {
+
+ if ((lstrcmpi(lpTextId, pThisSymbol->SymbolName)) == 0) {
+ // a matching symbol was found, so insert it's value
+ // and return (that's all that needs to be done
+ *pdwOffset = pThisSymbol->Value;
+ return TRUE;
+ }
+ }
+ // if here, then no matching symbol was found, and it's not
+ // a number, so return an error
+
+ SetLastError (ERROR_BAD_TOKEN_TYPE);
+ return FALSE;
+ } else {
+ // symbol was prefixed with a decimal number
+ return TRUE;
+ }
+}
+
+PLANGUAGE_LIST_ELEMENT
+FindLanguage (
+ IN PLANGUAGE_LIST_ELEMENT pFirstLang,
+ IN LPTSTR pLangId
+)
+/*++
+
+FindLanguage
+
+ searchs the list of languages and returns a pointer to the language
+ list entry that matches the pLangId string argument
+
+Arguments
+
+ pFirstLang
+
+ pointer to first language list element
+
+ pLangId
+
+ pointer to text string with language ID to look up
+
+Return Value
+
+ Pointer to matching language list entry
+ or NULL if no match
+
+--*/
+{
+ PLANGUAGE_LIST_ELEMENT pThisLang;
+
+ for (pThisLang = pFirstLang;
+ pThisLang;
+ pThisLang = pThisLang->pNextLang) {
+ if ((lstrcmpi(pLangId, pThisLang->LangId)) == 0) {
+ // match found so return pointer
+ return pThisLang;
+ }
+ }
+ return NULL; // no match found
+}
+
+BOOL
+AddEntryToLanguage (
+ PLANGUAGE_LIST_ELEMENT pLang,
+ LPTSTR lpValueKey,
+ DWORD dwType,
+ DWORD dwOffset,
+ LPTSTR lpIniFile
+)
+/*++
+
+AddEntryToLanguage
+
+ Add a text entry to the list of text entries for the specified language
+
+Arguments
+
+ pLang
+
+ pointer to language structure to update
+
+ lpValueKey
+
+ value key to look up in .ini file
+
+ dwOffset
+
+ numeric offset of name in registry
+
+ lpIniFile
+
+ ini file
+
+Return Value
+
+ TRUE if added successfully
+ FALSE if error
+ (see GetLastError for status)
+
+--*/
+{
+ LPTSTR lpLocalStringBuff;
+ DWORD dwSize;
+
+ lpLocalStringBuff = malloc (SMALL_BUFFER_SIZE);
+
+ if (!lpLocalStringBuff) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ dwSize = GetPrivateProfileString (
+ TEXT("text"), // section
+ lpValueKey, // key
+ TEXT("DefaultValue"), // default value
+ lpLocalStringBuff,
+ SMALL_BUFFER_SIZE,
+ lpIniFile);
+
+ if ((lstrcmpi(lpLocalStringBuff, TEXT("DefaultValue")))== 0) {
+ SetLastError (ERROR_BADKEY);
+ if (lpLocalStringBuff) free (lpLocalStringBuff);
+ return FALSE;
+ }
+
+ // key found, so load structure
+
+ if (!pLang->pThisName) {
+ // this is the first
+ pLang->pThisName =
+ malloc (sizeof (NAME_ENTRY) +
+ (lstrlen(lpLocalStringBuff) + 1) * sizeof (TCHAR));
+ if (!pLang->pThisName) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ if (lpLocalStringBuff) free (lpLocalStringBuff);
+ return FALSE;
+ } else {
+ pLang->pFirstName = pLang->pThisName;
+ }
+ } else {
+ pLang->pThisName->pNext =
+ malloc (sizeof (NAME_ENTRY) +
+ (lstrlen(lpLocalStringBuff) + 1) * sizeof (TCHAR));
+ if (!pLang->pThisName->pNext) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ if (lpLocalStringBuff) free (lpLocalStringBuff);
+ return FALSE;
+ } else {
+ pLang->pThisName = pLang->pThisName->pNext;
+ }
+ }
+
+ // pLang->pThisName now points to an uninitialized structre
+
+ pLang->pThisName->pNext = NULL;
+ pLang->pThisName->dwOffset = dwOffset;
+ pLang->pThisName->dwType = dwType;
+ pLang->pThisName->lpText = (LPTSTR)&(pLang->pThisName[1]); // string follows
+
+ lstrcpy (pLang->pThisName->lpText, lpLocalStringBuff);
+
+ if (lpLocalStringBuff) free (lpLocalStringBuff);
+
+ SetLastError (ERROR_SUCCESS);
+
+ return (TRUE);
+}
+
+BOOL
+LoadLanguageLists (
+ IN LPTSTR lpIniFile,
+ IN DWORD dwFirstCounter,
+ IN DWORD dwFirstHelp,
+ IN PSYMBOL_TABLE_ENTRY pFirstSymbol,
+ IN PLANGUAGE_LIST_ELEMENT pFirstLang
+)
+/*++
+
+LoadLanguageLists
+
+ Reads in the name and explain text definitions from the ini file and
+ builds a list of these items for each of the supported languages and
+ then combines all the entries into a sorted MULTI_SZ string buffer.
+
+Arguments
+
+ lpIniFile
+
+ file containing the definitions to add to the registry
+
+ dwFirstCounter
+
+ starting counter name index number
+
+ dwFirstHelp
+
+ starting help text index number
+
+ pFirstLang
+
+ pointer to first element in list of language elements
+
+Return Value
+
+ TRUE if all is well
+ FALSE if not
+ error is returned in GetLastError
+
+--*/
+{
+ LPTSTR lpTextIdArray;
+ LPTSTR lpLocalKey;
+ LPTSTR lpThisKey;
+ DWORD dwSize;
+ LPTSTR lpLang;
+ DWORD dwOffset;
+ DWORD dwType;
+ PLANGUAGE_LIST_ELEMENT pThisLang;
+
+ if (!(lpTextIdArray = malloc (SMALL_BUFFER_SIZE))) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ if (!(lpLocalKey = malloc (MAX_PATH))) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ if (lpTextIdArray) free (lpTextIdArray);
+ return FALSE;
+ }
+
+ // get list of text keys to look up
+
+ dwSize = GetPrivateProfileString (
+ TEXT("text"), // [text] section of .INI file
+ NULL, // return all keys
+ TEXT("DefaultKeyValue"), // default
+ lpTextIdArray, // return buffer
+ SMALL_BUFFER_SIZE, // buffer size
+ lpIniFile); // .INI file name
+
+ if ((lstrcmpi(lpTextIdArray, TEXT("DefaultKeyValue"))) == 0) {
+ // key not found, default returned
+ SetLastError (ERROR_NO_SUCH_GROUP);
+ if (lpTextIdArray) free (lpTextIdArray);
+ if (lpLocalKey) free (lpLocalKey);
+ return FALSE;
+ }
+
+ // do each key returned
+
+ for (lpThisKey=lpTextIdArray;
+ *lpThisKey;
+ lpThisKey += (lstrlen(lpThisKey) + 1)) {
+
+ lstrcpy (lpLocalKey, lpThisKey); // make a copy of the key
+
+ // parse key to see if it's in the correct format
+
+ if (ParseTextId(lpLocalKey, pFirstSymbol, &dwOffset, &lpLang, &dwType)) {
+ // so get pointer to language entry structure
+ pThisLang = FindLanguage (pFirstLang, lpLang);
+ if (pThisLang) {
+ if (!AddEntryToLanguage(pThisLang,
+ lpThisKey, dwType,
+ (dwOffset + ((dwType == TYPE_NAME) ? dwFirstCounter : dwFirstHelp)),
+ lpIniFile)) {
+ }
+ } else { // language not in list
+ }
+ } else { // unable to parse ID string
+ }
+ }
+
+ if (lpTextIdArray) free (lpTextIdArray);
+ if (lpLocalKey) free (lpLocalKey);
+ return TRUE;
+
+}
+
+BOOL
+SortLanguageTables (
+ PLANGUAGE_LIST_ELEMENT pFirstLang,
+ PDWORD pdwLastName,
+ PDWORD pdwLastHelp
+)
+/*++
+
+SortLangageTables
+
+ walks list of languages loaded, allocates and loads a sorted multi_SZ
+ buffer containing new entries to be added to current names/help text
+
+Arguments
+
+ pFirstLang
+
+ pointer to first element in list of languages
+
+ReturnValue
+
+ TRUE everything done as expected
+ FALSE error occurred, status in GetLastError
+
+--*/
+{
+ PLANGUAGE_LIST_ELEMENT pThisLang;
+
+ BOOL bSorted;
+
+ LPTSTR pNameBufPos, pHelpBufPos;
+
+ PNAME_ENTRY pThisName, pPrevName;
+
+ DWORD dwHelpSize, dwNameSize, dwSize;
+
+ if (!pdwLastName || !pdwLastHelp) {
+ SetLastError (ERROR_BAD_ARGUMENTS);
+ return FALSE;
+ }
+
+ for (pThisLang = pFirstLang;
+ pThisLang;
+ pThisLang = pThisLang->pNextLang) {
+ // do each language in list
+
+ // sort elements in list by value (offset) so that lowest is first
+
+ bSorted = FALSE;
+ while (!bSorted ) {
+ // point to start of list
+
+ pPrevName = pThisLang->pFirstName;
+ if (pPrevName) {
+ pThisName = pPrevName->pNext;
+ } else {
+ break; // no elements in this list
+ }
+
+ if (!pThisName) {
+ break; // only one element in the list
+ }
+ bSorted = TRUE; // assume that it's sorted
+
+ // go until end of list
+
+ while (pThisName->pNext) {
+ if (pThisName->dwOffset > pThisName->pNext->dwOffset) {
+ // switch 'em
+ pPrevName->pNext = pThisName->pNext;
+ pThisName->pNext = pThisName->pNext->pNext;
+ pThisName->pNext->pNext = pThisName;
+ bSorted = FALSE;
+ }
+ //move to next entry
+ pPrevName = pThisName;
+ pThisName = pThisName->pNext;
+ }
+ // if bSorted = TRUE , then we walked all the way down
+ // the list without changing anything so that's the end.
+ }
+
+ // with the list sorted, build the MULTI_SZ strings for the
+ // help and name text strings
+
+ // compute buffer size
+
+ dwNameSize = dwHelpSize = 0;
+ *pdwLastName = *pdwLastHelp = 0;
+
+ for (pThisName = pThisLang->pFirstName;
+ pThisName;
+ pThisName = pThisName->pNext) {
+ // compute buffer requirements for this entry
+ dwSize = SIZE_OF_OFFSET_STRING;
+ dwSize += lstrlen (pThisName->lpText);
+ dwSize += 1; // null
+ dwSize *= sizeof (TCHAR); // adjust for character size
+ // add to appropriate size register
+ if (pThisName->dwType == TYPE_NAME) {
+ dwNameSize += dwSize;
+ if (pThisName->dwOffset > *pdwLastName) {
+ *pdwLastName = pThisName->dwOffset;
+ }
+ } else if (pThisName->dwType == TYPE_HELP) {
+ dwHelpSize += dwSize;
+ if (pThisName->dwOffset > *pdwLastHelp) {
+ *pdwLastHelp = pThisName->dwOffset;
+ }
+ }
+ }
+
+ // allocate buffers for the Multi_SZ strings
+
+ pThisLang->NameBuffer = malloc (dwNameSize);
+ pThisLang->HelpBuffer = malloc (dwHelpSize);
+
+ if (!pThisLang->NameBuffer || !pThisLang->HelpBuffer) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return FALSE;
+ }
+
+ // fill in buffers with sorted strings
+
+ pNameBufPos = (LPTSTR)pThisLang->NameBuffer;
+ pHelpBufPos = (LPTSTR)pThisLang->HelpBuffer;
+
+ for (pThisName = pThisLang->pFirstName;
+ pThisName;
+ pThisName = pThisName->pNext) {
+ if (pThisName->dwType == TYPE_NAME) {
+ // load number as first 0-term. string
+ dwSize = _stprintf (pNameBufPos, TEXT("%d"), pThisName->dwOffset);
+ pNameBufPos += dwSize + 1; // save NULL term.
+ // load the text to match
+ lstrcpy (pNameBufPos, pThisName->lpText);
+ pNameBufPos += lstrlen(pNameBufPos) + 1;
+ } else if (pThisName->dwType == TYPE_HELP) {
+ // load number as first 0-term. string
+ dwSize = _stprintf (pHelpBufPos, TEXT("%d"), pThisName->dwOffset);
+ pHelpBufPos += dwSize + 1; // save NULL term.
+ // load the text to match
+ lstrcpy (pHelpBufPos, pThisName->lpText);
+ pHelpBufPos += lstrlen(pHelpBufPos) + 1;
+ }
+ }
+
+ // add additional NULL at end of string to terminate MULTI_SZ
+
+ *pHelpBufPos = TEXT('\0');
+ *pNameBufPos = TEXT('\0');
+
+ // compute size of MULTI_SZ strings
+
+ pThisLang->dwNameBuffSize = (DWORD)((PBYTE)pNameBufPos -
+ (PBYTE)pThisLang->NameBuffer) +
+ sizeof(TCHAR);
+ pThisLang->dwHelpBuffSize = (DWORD)((PBYTE)pHelpBufPos -
+ (PBYTE)pThisLang->HelpBuffer) +
+ sizeof(TCHAR);
+ }
+ return TRUE;
+}
+
+BOOL
+UpdateEachLanguage (
+ HKEY hPerflibRoot,
+ PLANGUAGE_LIST_ELEMENT pFirstLang
+)
+/*++
+
+UpdateEachLanguage
+
+ Goes through list of languages and adds the sorted MULTI_SZ strings
+ to the existing counter and explain text in the registry.
+ Also updates the "Last Counter and Last Help" values
+
+Arguments
+
+ hPerflibRoot
+
+ handle to Perflib key in the registry
+
+ pFirstLanguage
+
+ pointer to first language entry
+
+Return Value
+
+ TRUE all went as planned
+ FALSE an error occured, use GetLastError to find out what it was.
+
+--*/
+{
+
+ PLANGUAGE_LIST_ELEMENT pThisLang;
+
+ LPTSTR pHelpBuffer;
+ LPTSTR pNameBuffer;
+ LPTSTR pNewName;
+ LPTSTR pNewHelp;
+
+ DWORD dwBufferSize;
+ DWORD dwValueType;
+ DWORD dwCounterSize;
+ DWORD dwHelpSize;
+
+ HKEY hKeyThisLang;
+
+ LONG lStatus;
+
+ for (pThisLang = pFirstLang;
+ pThisLang;
+ pThisLang = pThisLang->pNextLang) {
+
+ lStatus = RegOpenKeyEx(
+ hPerflibRoot,
+ pThisLang->LangId,
+ RESERVED,
+ KEY_READ | KEY_WRITE,
+ &hKeyThisLang);
+
+ if (lStatus == ERROR_SUCCESS) {
+
+ // get size of counter names
+
+ dwBufferSize = 0;
+ lStatus = RegQueryValueEx (
+ hKeyThisLang,
+ Counters,
+ RESERVED,
+ &dwValueType,
+ NULL,
+ &dwBufferSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ return FALSE;
+ }
+
+ dwCounterSize = dwBufferSize;
+
+ // get size of help text
+
+ dwBufferSize = 0;
+ lStatus = RegQueryValueEx (
+ hKeyThisLang,
+ Help,
+ RESERVED,
+ &dwValueType,
+ NULL,
+ &dwBufferSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ return FALSE;
+ }
+
+ dwHelpSize = dwBufferSize;
+
+ // allocate new buffers
+
+ dwCounterSize += pThisLang->dwNameBuffSize;
+ pNameBuffer = malloc (dwCounterSize);
+
+ dwHelpSize += pThisLang->dwHelpBuffSize;
+ pHelpBuffer = malloc (dwHelpSize);
+
+ if (!pNameBuffer || !pHelpBuffer) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ return (FALSE);
+ }
+
+ // load current buffers into memory
+
+ // read counter names into buffer. Counter names will be stored as
+ // a MULTI_SZ string in the format of "###" "Name"
+
+ dwBufferSize = dwCounterSize;
+ lStatus = RegQueryValueEx (
+ hKeyThisLang,
+ Counters,
+ RESERVED,
+ &dwValueType,
+ (LPVOID)pNameBuffer,
+ &dwBufferSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ return FALSE;
+ }
+
+ // set pointer to location in buffer where new string should be
+ // appended: end of buffer - 1 (second null at end of MULTI_SZ
+
+ pNewName = (LPTSTR)((PBYTE)pNameBuffer + dwBufferSize - sizeof(TCHAR));
+
+ // adjust buffer length to take into account 2nd null from 1st
+ // buffer that has been overwritten
+
+ dwCounterSize -= sizeof(TCHAR);
+
+ // read explain text into buffer. Counter names will be stored as
+ // a MULTI_SZ string in the format of "###" "Text..."
+
+ dwBufferSize = dwHelpSize;
+ lStatus = RegQueryValueEx (
+ hKeyThisLang,
+ Help,
+ RESERVED,
+ &dwValueType,
+ (LPVOID)pHelpBuffer,
+ &dwBufferSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ return FALSE;
+ }
+
+ // set pointer to location in buffer where new string should be
+ // appended: end of buffer - 1 (second null at end of MULTI_SZ
+
+ pNewHelp = (LPTSTR)((PBYTE)pHelpBuffer + dwBufferSize - sizeof(TCHAR));
+
+ // adjust buffer length to take into account 2nd null from 1st
+ // buffer that has been overwritten
+
+ dwHelpSize -= sizeof(TCHAR);
+
+ // append new strings to end of current strings
+
+ memcpy (pNewHelp, pThisLang->HelpBuffer, pThisLang->dwHelpBuffSize);
+ memcpy (pNewName, pThisLang->NameBuffer, pThisLang->dwNameBuffSize);
+
+ lStatus = RegSetValueEx (
+ hKeyThisLang,
+ Counters,
+ RESERVED,
+ REG_MULTI_SZ,
+ (LPBYTE)pNameBuffer,
+ dwCounterSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ return FALSE;
+ }
+
+ lStatus = RegSetValueEx (
+ hKeyThisLang,
+ Help,
+ RESERVED,
+ REG_MULTI_SZ,
+ (LPBYTE)pHelpBuffer,
+ dwHelpSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ return FALSE;
+ }
+ free (pNameBuffer);
+ free (pHelpBuffer);
+ CloseHandle (hKeyThisLang);
+ } else {
+ }
+ }
+
+ return TRUE;
+}
+
+BOOL
+UpdateRegistry (
+ LPTSTR lpIniFile,
+ HKEY hKeyMachine,
+ LPTSTR lpDriverName,
+ PLANGUAGE_LIST_ELEMENT pFirstLang,
+ PSYMBOL_TABLE_ENTRY pFirstSymbol
+)
+/*++
+
+UpdateRegistry
+
+ - checks, and if not busy, sets the "busy" key in the registry
+ - Reads in the text and help definitions from the .ini file
+ - Reads in the current contents of the HELP and COUNTER names
+ - Builds a sorted MULTI_SZ struct containing the new definitions
+ - Appends the new MULTI_SZ to the current as read from the registry
+ - loads the new MULTI_SZ string into the registry
+ - updates the keys in the driver's entry and Perflib's entry in the
+ registry (e.g. first, last, etc)
+ - clears the "busy" key
+
+Arguments
+
+ lpIniFile
+ pathname to .ini file conatining definitions
+
+ hKeyMachine
+ handle to HKEY_LOCAL_MACHINE in registry on system to
+ update counters for.
+
+ lpDriverName
+ Name of device driver to load counters for
+
+ pFirstLang
+ pointer to first element in language structure list
+
+ pFirstSymbol
+ pointer to first element in symbol definition list
+
+
+Return Value
+
+ TRUE if registry updated successfully
+ FALSE if registry not updated
+ (This routine will print an error message to stdout if an error
+ is encountered).
+
+--*/
+{
+
+ HKEY hDriverPerf = NULL;
+ HKEY hPerflib = NULL;
+
+ LPTSTR lpDriverKeyPath;
+
+ DWORD dwType;
+ DWORD dwSize;
+
+ DWORD dwFirstDriverCounter;
+ DWORD dwFirstDriverHelp;
+ DWORD dwLastDriverCounter;
+ DWORD dwLastPerflibCounter;
+ DWORD dwLastPerflibHelp;
+
+ BOOL bStatus;
+ LONG lStatus;
+
+ bStatus = FALSE;
+
+ // allocate temporary buffers
+ lpDriverKeyPath = malloc (MAX_PATH * sizeof(TCHAR));
+
+ if (!lpDriverKeyPath) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ goto UpdateRegExit;
+ }
+
+ // build driver key path string
+
+ lstrcpy (lpDriverKeyPath, DriverPathRoot);
+ lstrcat (lpDriverKeyPath, Slash);
+ lstrcat (lpDriverKeyPath, lpDriverName);
+ lstrcat (lpDriverKeyPath, Slash);
+ lstrcat (lpDriverKeyPath, Performance);
+
+ // open keys to registry
+ // open key to driver's performance key
+
+ lStatus = RegOpenKeyEx (
+ hKeyMachine,
+ lpDriverKeyPath,
+ RESERVED,
+ KEY_WRITE | KEY_READ,
+ &hDriverPerf);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ goto UpdateRegExit;
+ }
+
+ // open key to perflib's "root" key
+
+ lStatus = RegOpenKeyEx (
+ hKeyMachine,
+ NamesKey,
+ RESERVED,
+ KEY_WRITE | KEY_READ,
+ &hPerflib);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ goto UpdateRegExit;
+ }
+
+ // get "last" values from PERFLIB
+
+ dwType = 0;
+ dwLastPerflibCounter = 0;
+ dwSize = sizeof (dwLastPerflibCounter);
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ LastCounter,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwLastPerflibCounter,
+ &dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // this request should always succeed, if not then worse things
+ // will happen later on, so quit now and avoid the trouble.
+ SetLastError (lStatus);
+ goto UpdateRegExit;
+ }
+
+ // get last help value now
+
+ dwType = 0;
+ dwLastPerflibHelp = 0;
+ dwSize = sizeof (dwLastPerflibHelp);
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ LastHelp,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwLastPerflibHelp,
+ &dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ // this request should always succeed, if not then worse things
+ // will happen later on, so quit now and avoid the trouble.
+ SetLastError (lStatus);
+ goto UpdateRegExit;
+ }
+
+ // get last help value now
+
+ dwType = 0;
+ dwSize = sizeof (dwSystemVersion);
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ VersionStr,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwSystemVersion,
+ &dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ dwSystemVersion = OLD_VERSION;
+ }
+
+ if ( dwSystemVersion != OLD_VERSION )
+ {
+ // ERROR. The caller does not check the version. It is the caller
+ // fault
+ goto UpdateRegExit;
+ }
+
+ // see if this driver's counter names have already been installed
+ // by checking to see if LastCounter's value is less than Perflib's
+ // Last Counter
+
+ dwType = 0;
+ dwLastDriverCounter = 0;
+ dwSize = sizeof (dwLastDriverCounter);
+ lStatus = RegQueryValueEx (
+ hDriverPerf,
+ LastCounter,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwLastDriverCounter,
+ &dwSize);
+
+ if (lStatus == ERROR_SUCCESS) {
+ // if key found, then compare with perflib value and exit this
+ // procedure if the driver's last counter is <= to perflib's last
+ //
+ // if key not found, then continue with installation
+ // on the assumption that the counters have not been installed
+
+ if (dwLastDriverCounter <= dwLastPerflibCounter) {
+ SetLastError (ERROR_SUCCESS);
+ goto UpdateRegExit;
+ }
+ }
+
+ // everything looks like it's ready to go so first check the
+ // busy indicator
+
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ Busy,
+ RESERVED,
+ &dwType,
+ NULL,
+ &dwSize);
+
+ if (lStatus == ERROR_SUCCESS) { // perflib is in use at the moment
+ return ERROR_BUSY;
+ }
+
+ // set the "busy" indicator under the PERFLIB key
+
+ dwSize = lstrlen(lpDriverName) * sizeof (TCHAR);
+ lStatus = RegSetValueEx (
+ hPerflib,
+ Busy,
+ RESERVED,
+ REG_SZ,
+ (LPBYTE)lpDriverName,
+ dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ SetLastError (lStatus);
+ goto UpdateRegExit;
+ }
+
+ // increment (by 2) the last counters so they point to the first
+ // unused index after the existing names and then
+ // set the first driver counters
+
+ dwFirstDriverCounter = dwLastPerflibCounter += 2;
+ dwFirstDriverHelp = dwLastPerflibHelp += 2;
+
+ // load .INI file definitions into language tables
+
+ if (!LoadLanguageLists (lpIniFile, dwLastPerflibCounter, dwLastPerflibHelp,
+ pFirstSymbol, pFirstLang)) {
+ // error message is displayed by LoadLanguageLists so just abort
+ // error is in GetLastError already
+ goto UpdateRegExit;
+ }
+
+ // all the symbols and definitions have been loaded into internal
+ // tables. so now they need to be sorted and merged into a multiSZ string
+ // this routine also updates the "last" counters
+
+ if (!SortLanguageTables (pFirstLang, &dwLastPerflibCounter, &dwLastPerflibHelp)) {
+ goto UpdateRegExit;
+ }
+
+ if (!UpdateEachLanguage (hPerflib, pFirstLang)) {
+ goto UpdateRegExit;
+ }
+
+ // update last counters for driver and perflib
+
+ // perflib...
+
+ lStatus = RegSetValueEx(
+ hPerflib,
+ LastCounter,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwLastPerflibCounter,
+ sizeof(DWORD));
+
+ lStatus = RegSetValueEx(
+ hPerflib,
+ LastHelp,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwLastPerflibHelp,
+ sizeof(DWORD));
+
+ // and the driver
+
+ lStatus = RegSetValueEx(
+ hDriverPerf,
+ LastCounter,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwLastPerflibCounter,
+ sizeof(DWORD));
+
+ lStatus = RegSetValueEx(
+ hDriverPerf,
+ LastHelp,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwLastPerflibHelp,
+ sizeof(DWORD));
+
+ lStatus = RegSetValueEx(
+ hDriverPerf,
+ FirstCounter,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwFirstDriverCounter,
+ sizeof(DWORD));
+
+ lStatus = RegSetValueEx(
+ hDriverPerf,
+ FirstHelp,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwFirstDriverHelp,
+ sizeof(DWORD));
+
+ bStatus = TRUE;
+
+ // free temporary buffers
+UpdateRegExit:
+ // clear busy flag
+
+ lStatus = RegDeleteValue (
+ hPerflib,
+ Busy);
+
+ // free temporary buffers
+
+ if (lpDriverKeyPath) free (lpDriverKeyPath);
+ if (hDriverPerf) CloseHandle (hDriverPerf);
+ if (hPerflib) CloseHandle (hPerflib);
+
+ return bStatus;
+}
+
+BOOL FAR PASCAL lodctr(DWORD argc,LPSTR argv[], LPSTR *ppszResult )
+/*++
+
+main
+
+
+
+Arguments
+
+
+ReturnValue
+
+ 0 (ERROR_SUCCESS) if command was processed
+ Non-Zero if command error was detected.
+
+--*/
+{
+ LPTSTR lpIniFile;
+ LPTSTR lpDriverName;
+
+ LANGUAGE_LIST_ELEMENT LangList;
+ PSYMBOL_TABLE_ENTRY SymbolTable = NULL;
+ PSYMBOL_TABLE_ENTRY pThisSymbol = NULL;
+
+ BOOL fReturn = TRUE;
+
+ lpIniFile = malloc( MAX_PATH * sizeof(TCHAR));
+ lpDriverName = malloc (MAX_PATH * sizeof (TCHAR));
+
+ wsprintfA( achBuff, "{\"NO_ERROR\"}");
+
+ if ( argc == 1) {
+ MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, argv[0], -1, lpIniFile, MAX_PATH);
+
+ if (!GetDriverName (lpIniFile, &lpDriverName)) {
+ wsprintfA(achBuff,"{\"ERROR\"}");
+ fReturn = FALSE;
+ goto EndOfMain;
+ }
+
+ if (!BuildLanguageTables(lpIniFile, &LangList)) {
+ wsprintfA (achBuff, "{\"ERROR\"}");
+ fReturn = FALSE;
+ goto EndOfMain;
+ }
+
+ if (!LoadIncludeFile(lpIniFile, &SymbolTable)) {
+ // open errors displayed in routine
+ fReturn = FALSE;
+ goto EndOfMain;
+ }
+
+ if (!UpdateRegistry(lpIniFile,
+ HKEY_LOCAL_MACHINE,
+ lpDriverName,
+ &LangList,
+ SymbolTable)) {
+ wsprintfA (achBuff, "{\"ERROR\"}");
+ fReturn = FALSE;
+ }
+
+ }
+
+EndOfMain:
+
+ if (lpIniFile) free (lpDriverName);
+ if (lpDriverName) free (lpDriverName);
+
+ *ppszResult = achBuff;
+
+ return (fReturn); // success
+}
diff --git a/private/nw/install/setupdll/makefile b/private/nw/install/setupdll/makefile
new file mode 100644
index 000000000..7686b2955
--- /dev/null
+++ b/private/nw/install/setupdll/makefile
@@ -0,0 +1,10 @@
+#
+# 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
+#
+
+USE_CRTDLL=1
+
+!INCLUDE $(NTMAKEENV)\makefile.def
+!INCLUDE rules.mk
diff --git a/private/nw/install/setupdll/nwcfg.cxx b/private/nw/install/setupdll/nwcfg.cxx
new file mode 100644
index 000000000..1d31aca91
--- /dev/null
+++ b/private/nw/install/setupdll/nwcfg.cxx
@@ -0,0 +1,318 @@
+/**********************************************************************/
+/** Microsoft Windows NT **/
+/** Copyright(c) Microsoft Corp., 1991 **/
+/**********************************************************************/
+
+/*
+
+ nwcfg.cxx
+ netware configuration source code.
+
+ history:
+ terryk 05/07/93 Created
+*/
+
+
+#if defined(DEBUG)
+static const char szFileName[] = __FILE__;
+#define _FILENAME_DEFINED_ONCE szFileName
+#endif
+
+#define APIERR LONG
+
+extern "C"
+{
+
+#include <windows.h>
+#include <port1632.h>
+
+
+#include <winspool.h>
+
+// exported functions
+
+BOOL FAR PASCAL AddNetwarePrinterProvidor( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL DeleteNetwarePrinterProvidor( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL AppendSzToFile( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL GetKernelVersion( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+
+extern HINSTANCE ThisDLLHandle;
+}
+
+#define UNREFERENCED(x) ((void)(x))
+#include <nwcfg.hxx>
+#include <nwcfg.h>
+
+
+/*******************************************************************
+
+ NAME: AddNetwarePrinterProvidor
+
+ SYNOPSIS: This is a wrapper routine for called AddPrintProvidor. It
+ should be called from inf file if the user installs netware.
+
+ ENTRY: NONE from inf file.
+
+ RETURN: BOOL - TRUE for success.
+
+ HISTORY:
+ terryk 07-May-1993 Created
+
+********************************************************************/
+
+#define PROVIDER_DLL_NAME "nwprovau.dll"
+#define MAX_PROVIDER_NAME_LEN 512
+typedef BOOL (WINAPI *T_AddPrintProvidor)(LPSTR pName,DWORD Level,LPBYTE pMonitors);
+typedef BOOL (WINAPI *T_DeletePrintProvidor)(LPSTR pName,LPSTR pEnv, LPSTR pMon);
+
+
+BOOL FAR PASCAL AddNetwarePrinterProvidor( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ UNREFERENCED( nArgs );
+
+ PROVIDOR_INFO_1 ProvidorInfo1;
+
+ ProvidorInfo1.pEnvironment = (LPSTR) NULL;
+ ProvidorInfo1.pDLLName = PROVIDER_DLL_NAME;
+
+ APIERR err = 0;
+ do {
+ CHAR buf[MAX_PROVIDER_NAME_LEN];
+ LPSTR lpProviderName = (LPSTR)buf;
+ if ( lpProviderName == NULL )
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+ if ( !LoadString( ThisDLLHandle,
+ PROVIDER_NAME,
+ lpProviderName,
+ MAX_PROVIDER_NAME_LEN ) )
+ {
+ err = ::GetLastError();
+ break;
+ }
+
+ ProvidorInfo1.pName = lpProviderName;
+
+
+
+ HINSTANCE hDll = ::LoadLibraryA( "winspool.drv" );
+ if ( hDll == NULL )
+ {
+ err = ::GetLastError();
+ break;
+ }
+
+ FARPROC pAddPrintProvidor = ::GetProcAddress( hDll, "AddPrintProvidorA" );
+
+ if ( pAddPrintProvidor == NULL )
+ {
+ err = ::GetLastError();
+ } else if ( !(*(T_AddPrintProvidor)pAddPrintProvidor)((LPSTR) NULL,1,(LPBYTE)&ProvidorInfo1))
+ {
+ err = ::GetLastError();
+ }
+
+ if ( hDll )
+ ::FreeLibrary( hDll );
+
+ } while (FALSE);
+ wsprintfA( achBuff, "{\"%d\"}", err );
+ *ppszResult = achBuff;
+
+ return TRUE;
+}
+
+BOOL FAR PASCAL DeleteNetwarePrinterProvidor( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ UNREFERENCED( nArgs );
+ UNREFERENCED( apszArgs );
+
+ APIERR err = 0;
+
+ do {
+ HINSTANCE hDll = ::LoadLibraryA( "winspool.drv" );
+ if ( hDll == NULL )
+ {
+ err = ::GetLastError();
+ break;
+ }
+
+ FARPROC pDeletePrintProvidor = ::GetProcAddress( hDll, "DeletePrintProvidorA" );
+
+ if ( pDeletePrintProvidor == NULL )
+ {
+ err = ::GetLastError();
+ }
+ else
+ {
+ CHAR buf[MAX_PROVIDER_NAME_LEN];
+ LPSTR lpProviderName = (LPSTR)buf;
+ if ( lpProviderName == NULL )
+ {
+ err = ERROR_NOT_ENOUGH_MEMORY;
+ break;
+ }
+ if ( nArgs == 1 )
+ {
+ lpProviderName = apszArgs[0];
+ } else
+ {
+ if ( !LoadString( ThisDLLHandle,
+ PROVIDER_NAME,
+ lpProviderName,
+ MAX_PROVIDER_NAME_LEN ) )
+ {
+ err = ::GetLastError();
+ }
+ }
+ if ( !(*(T_DeletePrintProvidor)pDeletePrintProvidor)( (LPSTR) NULL,
+ (LPSTR) NULL,
+ lpProviderName))
+ {
+ err = ::GetLastError();
+ }
+ }
+
+ if ( hDll )
+ ::FreeLibrary ( hDll );
+
+ } while (FALSE);
+ wsprintfA( achBuff, "{\"%d\"}", err );
+ *ppszResult = achBuff;
+
+ return TRUE;
+}
+
+/*******************************************************************
+
+ NAME: AppendSzToFile
+
+ SYNOPSIS: Append a string to a file.
+
+ ENTRY: Args[0] - FileName string
+ Args[1] - String to be added to the file
+
+ RETURN: BOOL - TRUE for success.
+
+ HISTORY:
+ terryk 07-May-1993 Created
+
+********************************************************************/
+
+BOOL FAR PASCAL
+AppendSzToFile( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ UNREFERENCED( nArgs );
+
+ DWORD BytesWritten;
+ HANDLE hfile;
+ LPSTR szFileName = apszArgs[0];
+ LPSTR szAddOnSz = apszArgs[1];
+
+ //
+ // Open the file
+ //
+
+ hfile = CreateFile(
+ szFileName,
+ GENERIC_WRITE | GENERIC_READ,
+ FILE_SHARE_READ,
+ (struct _SECURITY_ATTRIBUTES *) NULL,
+ OPEN_ALWAYS,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+
+ if (hfile == (HANDLE)0xffffffff) {
+ wsprintfA( achBuff, "{ Cannot Open File: \"%s\"}", szFileName );
+ *ppszResult = achBuff;
+ return FALSE;
+ }
+
+ //
+ // Go to end of file
+ //
+
+ SetFilePointer (
+ hfile,
+ 0,
+ (PLONG) NULL,
+ FILE_END
+ );
+
+ //
+ // Append string passed in at the end of the file
+ //
+
+ WriteFile (
+ hfile,
+ szAddOnSz,
+ lstrlen( szAddOnSz ),
+ &BytesWritten,
+ (struct _OVERLAPPED *) NULL
+ );
+
+ CloseHandle (hfile);
+ wsprintfA( achBuff, "{\"%d\"}", 0 );
+ *ppszResult = achBuff;
+ return TRUE;
+}
+
+/*******************************************************************
+
+ NAME: GetKernelVersion
+
+ SYNOPSIS: Get the current kernel version number
+
+ ENTRY: NONE from inf file.
+
+ RETURN: BOOL - TRUE for success.
+ The return number is the kernel build number.
+ {"MajorVerion","MinorVersion","BuildNumber","PatchNumber"}
+
+ HISTORY:
+ terryk 24-Sept-1993 Created
+
+********************************************************************/
+
+BOOL FAR PASCAL
+GetKernelVersion( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ UNREFERENCED( nArgs );
+
+ DWORD wVer;
+ LONG nSubVersion;
+ LONG nVersion;
+
+ LPCSTR lpszRegName = "SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion";
+ HKEY hsubkey ;
+ DWORD dwZero = 0;
+ DWORD dwRegValueType;
+ DWORD dwRegValue;
+ DWORD cbRegValue;
+
+ wVer = GetVersion();
+ nSubVersion = GETMINORVERSION(wVer);
+ nVersion = GETMAJORVERSION(wVer);
+
+ cbRegValue = sizeof(dwRegValue);
+
+ if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
+ lpszRegName, dwZero, KEY_QUERY_VALUE, &hsubkey) ||
+ RegQueryValueEx(hsubkey, "CSDVersion", (LPDWORD)NULL,
+ &dwRegValueType, (LPBYTE)&dwRegValue, &cbRegValue) ||
+ dwRegValueType != REG_DWORD
+ ) {
+ wsprintf(achBuff,"{\"%d\",\"%d\",\"%d\",\"%d\"}", nVersion, nSubVersion, wVer >> 16, 0);
+ } else {
+ wsprintf(achBuff,"{\"%d\",\"%d\",\"%d\",\"%d\"}", nVersion, nSubVersion, wVer >> 16, dwRegValue);
+ }
+ if (hsubkey != NULL) {
+ RegCloseKey (hsubkey);
+ }
+ *ppszResult = achBuff;
+ return TRUE;
+}
+
diff --git a/private/nw/install/setupdll/nwcfg.def b/private/nw/install/setupdll/nwcfg.def
new file mode 100644
index 000000000..3fa95f62b
--- /dev/null
+++ b/private/nw/install/setupdll/nwcfg.def
@@ -0,0 +1,19 @@
+LIBRARY NWCFG
+
+DESCRIPTION 'Client Service for Netware configuration dll $V'
+
+EXPORTS
+ AddNetwarePrinterProvidor @1
+ DeleteNetwarePrinterProvidor @2
+ AppendSzToFile @3
+ RemoveSzFromFile @4
+ GetKernelVersion @5
+ SetEverybodyPermission @6
+ lodctr @7
+ unlodctr @8
+ DeleteGatewayPassword @9
+ SetFileSysChangeValue @10
+
+ CleanupRegistryForNWCS @11
+ SetupRegistryForNWCS @12
+
diff --git a/private/nw/install/setupdll/nwcfg.h b/private/nw/install/setupdll/nwcfg.h
new file mode 100644
index 000000000..6aa91281c
--- /dev/null
+++ b/private/nw/install/setupdll/nwcfg.h
@@ -0,0 +1,22 @@
+/**********************************************************************/
+/** Microsoft Windows NT **/
+/** Copyright(c) Microsoft Corp., 1991 **/
+/**********************************************************************/
+
+/*
+
+ nwcfg.h
+
+ history:
+ thomaspa 1/24/94 Created
+*/
+
+
+#ifndef _NWCFG_H_
+#define _NWCFG_H_
+
+#define PROVIDER_NAME 101
+
+#endif // _NWCFG_H_
+
+
diff --git a/private/nw/install/setupdll/nwcfg.hxx b/private/nw/install/setupdll/nwcfg.hxx
new file mode 100644
index 000000000..db856a517
--- /dev/null
+++ b/private/nw/install/setupdll/nwcfg.hxx
@@ -0,0 +1,28 @@
+/**********************************************************************/
+/** Microsoft Windows NT **/
+/** Copyright(c) Microsoft Corp., 1991 **/
+/**********************************************************************/
+
+/*
+
+ nwcfg.hxx
+ Header for output buffer.
+
+ history:
+ terryk 09/30/93 Created
+*/
+
+
+#ifndef _NWCFG_HXX_
+#define _NWCFG_HXX_
+
+/* Global return buffer */
+char achBuff[2000];
+
+#else
+
+extern char achBuff[2000];
+
+#endif // _NWCFG_HXX_
+
+
diff --git a/private/nw/install/setupdll/nwcfg.prf b/private/nw/install/setupdll/nwcfg.prf
new file mode 100644
index 000000000..8b1378917
--- /dev/null
+++ b/private/nw/install/setupdll/nwcfg.prf
@@ -0,0 +1 @@
+
diff --git a/private/nw/install/setupdll/nwcfg.rc b/private/nw/install/setupdll/nwcfg.rc
new file mode 100644
index 000000000..ba1ddfa99
--- /dev/null
+++ b/private/nw/install/setupdll/nwcfg.rc
@@ -0,0 +1,20 @@
+#include "windows.h"
+#include "nwcfg.h"
+
+
+stringtable
+begin
+ PROVIDER_NAME, "NetWare or Compatible Network"
+end
+
+#include <ntverp.h>
+
+#define VER_FILETYPE VFT_DLL
+#define VER_FILESUBTYPE VFT2_UNKNOWN
+#define VER_FILEDESCRIPTION_STR "NWC Configuration DLL"
+#define VER_INTERNALNAME_STR "nwcfg.dll"
+#define VER_ORIGINALFILENAME_STR "nwcfg.dll"
+
+#include "common.ver"
+
+
diff --git a/private/nw/install/setupdll/removesz.c b/private/nw/install/setupdll/removesz.c
new file mode 100644
index 000000000..00757ae6f
--- /dev/null
+++ b/private/nw/install/setupdll/removesz.c
@@ -0,0 +1,58 @@
+/*++
+Copyright (c) 1990 Microsoft Corporation
+
+RemoveSzFromFile() - remove a specified string from the file
+
+--*/
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nwcfg.hxx>
+
+
+BOOL
+RemoveSzFromFile( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ FILE * hsrcfile;
+ FILE * hdesfile;
+ char * pszTempname;
+ char szInput[1000];
+
+ pszTempname = tmpnam(NULL);
+ wsprintf(achBuff,"{1}");
+ *ppszResult = achBuff;
+ if ( nArgs != 2 )
+ {
+ return(FALSE);
+ }
+ hsrcfile = fopen(apszArgs[0],"r");
+ hdesfile = fopen(pszTempname,"w");
+ if (( hsrcfile != NULL ) && ( hdesfile != NULL ))
+ {
+ while (fgets(szInput,1000,hsrcfile))
+ {
+ if (_stricmp(szInput,apszArgs[1])!=0)
+ {
+ fputs(szInput,hdesfile);
+ }
+ }
+ }
+ if ( hsrcfile != NULL )
+ fclose(hsrcfile);
+ if ( hdesfile != NULL )
+ fclose(hdesfile);
+ if (( hsrcfile != NULL ) && ( hdesfile != NULL ))
+ {
+ CopyFileA(pszTempname,apszArgs[0], FALSE);
+ DeleteFileA(pszTempname);
+ }
+
+ wsprintf(achBuff,"{0}");
+ *ppszResult = achBuff;
+ return(TRUE);
+}
diff --git a/private/nw/install/setupdll/rules.mk b/private/nw/install/setupdll/rules.mk
new file mode 100644
index 000000000..232ff4c33
--- /dev/null
+++ b/private/nw/install/setupdll/rules.mk
@@ -0,0 +1,4 @@
+# @@ COPY_RIGHT_HERE
+# @@ ROADMAP :: The Rules.mk for the Network Control Panel Applet
+#
+
diff --git a/private/nw/install/setupdll/setvalue.c b/private/nw/install/setupdll/setvalue.c
new file mode 100644
index 000000000..bfaf073cf
--- /dev/null
+++ b/private/nw/install/setupdll/setvalue.c
@@ -0,0 +1,696 @@
+/**********************************************************************/
+/** Microsoft Windows NT **/
+/** Copyright(c) Microsoft Corp., 1991 **/
+/**********************************************************************/
+
+/*
+
+ setvalue.c
+ Code to enable SetValue for everyone.
+
+ history:
+ terryk 09/30/93 Created
+*/
+
+
+#if defined(DEBUG)
+static const char szFileName[] = __FILE__;
+#define _FILENAME_DEFINED_ONCE szFileName
+#endif
+
+#include <string.h>
+
+#include <nt.h>
+#include <ntrtl.h>
+#include <nturtl.h>
+#include <windows.h>
+#include <stdio.h>
+#include <stdlib.h>
+
+#include <nwlsa.h>
+#include <nwapi.h>
+#include <nwcfg.h>
+#include <nwcfg.hxx>
+
+extern char achBuff[];
+
+// exported functions
+
+BOOL FAR PASCAL SetFileSysChangeValue( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL SetEverybodyPermission( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL SetupRegistryForNWCS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL SetupRegistryWorker( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL DeleteGatewayPassword( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+BOOL FAR PASCAL CleanupRegistryForNWCS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult );
+
+//
+// structure for registry munging
+//
+
+typedef struct REG_ENTRY_ {
+ DWORD Operation ;
+ LONG Level ;
+ LPWSTR s1 ;
+ LPWSTR s2 ;
+} REG_ENTRY ;
+
+//
+// local routines
+//
+
+DWORD SetupShellExtensions(REG_ENTRY RegEntries[], DWORD dwNumEntries) ;
+
+typedef DWORD (*LPNWCLEANUPGATEWAYSHARES)(VOID) ;
+
+// Values & Tables that define registry data
+
+#define MAX_REG_LEVEL 10
+
+#define CREATE_ABS 1 // create/open a key with absolute path
+#define CREATE_REL 2 // create/open a key with relative path
+#define VALUE_STR 3 // write a string value
+#define DELETE_ABS 4 // delete key with absolute path
+#define DELETE_REL 5 // delete key with relative path
+#define DELETE_VAL 6 // delete a value
+#define DROP_STACK 7 // drop stack by one
+
+REG_ENTRY RegCreateEntries[] =
+{
+ {CREATE_ABS,0,L"SOFTWARE\\Classes\\NetWare_or_Compatible_Network", NULL},
+ {DELETE_REL,0,L"shellex\\ContextMenuHandlers\\NetWareMenus", NULL},
+ {DELETE_REL,0,L"shellex\\ContextMenuHandlers", NULL},
+ {DELETE_REL,0,L"shellex\\PropertySheetHandlers\\NetWarePage", NULL},
+ {DELETE_REL,0,L"shellex\\PropertySheetHandlers", NULL},
+ {DELETE_REL,0,L"shellex", NULL},
+ {DROP_STACK,0,NULL,NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\NetWare_or_Compatible_Network", NULL},
+
+ {CREATE_ABS, 0,L"SOFTWARE\\Classes\\Network\\Type", NULL},
+ {CREATE_REL,+1, L"3", NULL},
+ {CREATE_REL,+1, L"shellex", NULL},
+ {CREATE_REL,+1, L"ContextMenuHandlers", NULL},
+ {CREATE_REL,+1, L"NetWareMenus", NULL},
+ {VALUE_STR,0, L"", L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}"},
+ {CREATE_REL,-1, L"PropertySheetHandlers", NULL},
+ {CREATE_REL,+1, L"NetWarePage", NULL},
+ {VALUE_STR,0, L"", L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}"},
+ {CREATE_ABS, 0,L"SOFTWARE\\Classes\\CLSID", NULL},
+ {CREATE_REL,+1, L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}", NULL},
+ {VALUE_STR,0, L"", L"NetWare Objects"},
+ {CREATE_REL,+1, L"InProcServer32", NULL},
+ {VALUE_STR,0, L"", L"nwprovau.dll"},
+ {VALUE_STR,0, L"ThreadingModel", L"Apartment"},
+ {CREATE_REL,-1, L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}", NULL},
+ {VALUE_STR,0, L"", L"NetWare UNC Folder Menu"},
+ {CREATE_REL,+1, L"InProcServer32", NULL},
+ {VALUE_STR,0, L"", L"nwprovau.dll"},
+ {VALUE_STR,0, L"ThreadingModel", L"Apartment"},
+ {CREATE_REL,-1, L"{52c68510-09a0-11cf-8daa-00aa004a5691}", NULL},
+ {VALUE_STR,0, L"", L"NetWare Hood Verbs"},
+ {CREATE_REL,+1, L"InProcServer32", NULL},
+ {VALUE_STR,0, L"", L"nwprovau.dll"},
+ {VALUE_STR,0, L"ThreadingModel", L"Apartment"},
+ {CREATE_REL,-1, L"{208D2C60-3AEA-1069-A2D7-08002B30309D}", NULL},
+ {CREATE_REL,+1, L"shellex", NULL},
+ {CREATE_REL,+1, L"ContextMenuHandlers", NULL},
+ {CREATE_REL,+1, L"NetWareMenus", NULL},
+ {VALUE_STR,0, L"", L"{52c68510-09a0-11cf-8daa-00aa004a5691}"},
+ {CREATE_ABS, 0,L"SOFTWARE\\Classes\\Folder", NULL},
+ {CREATE_REL,+1, L"shellex", NULL},
+ {CREATE_REL,+1, L"ContextMenuHandlers", NULL},
+ {CREATE_REL,+1, L"NetWareUNCMenu", NULL},
+ {VALUE_STR,0, L"", L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}"},
+ {CREATE_ABS, 0,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion", NULL},
+ {CREATE_REL,+1, L"Shell Extensions", NULL},
+ {CREATE_REL,+1, L"Approved", NULL},
+ {VALUE_STR,0, L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}", L"Shell extensions for NetWare"},
+ {VALUE_STR,0, L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}", L"Shell extensions for NetWare"},
+ {VALUE_STR,0, L"{52c68510-09a0-11cf-8daa-00aa004a5691}", L"Shell extensions for NetWare"}
+} ;
+
+REG_ENTRY RegDeleteEntries[] =
+{
+ {CREATE_ABS,0,L"SOFTWARE\\Classes\\Network\\Type\\3", NULL},
+ {DELETE_REL,0,L"shellex\\ContextMenuHandlers\\NetWareMenus", NULL},
+ {DELETE_REL,0,L"shellex\\ContextMenuHandlers", NULL},
+ {DELETE_REL,0,L"shellex\\PropertySheetHandlers\\NetWarePage", NULL},
+ {DELETE_REL,0,L"shellex\\PropertySheetHandlers", NULL},
+ {DELETE_REL,0,L"shellex", NULL},
+ {DROP_STACK,0,NULL,NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\Network\\Type\\3", NULL},
+
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{8e9d6600-f84a-11ce-8daa-00aa004a5691}\\InProcServer32", NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{8e9d6600-f84a-11ce-8daa-00aa004a5691}", NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{e3f2bac0-099f-11cf-8daa-00aa004a5691}\\InProcServer32", NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{e3f2bac0-099f-11cf-8daa-00aa004a5691}", NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{52c68510-09a0-11cf-8daa-00aa004a5691}\\InProcServer32", NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{52c68510-09a0-11cf-8daa-00aa004a5691}", NULL},
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\CLSID\\{208D2C60-3AEA-1069-A2D7-08002B30309D}\\shellex\\ContextMenuHandlers\\NetWareMenus", NULL},
+
+ {DELETE_ABS,0,L"SOFTWARE\\Classes\\Folder\\shellex\\ContextMenuHandlers\\NetWareUNCMenu", NULL},
+ {CREATE_ABS,0,L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Shell Extensions\\Approved", NULL},
+ {DELETE_VAL,0,L"{8e9d6600-f84a-11ce-8daa-00aa004a5691}", NULL},
+ {DELETE_VAL,0,L"{e3f2bac0-099f-11cf-8daa-00aa004a5691}", NULL},
+ {DELETE_VAL,0,L"{52c68510-09a0-11cf-8daa-00aa004a5691}", NULL}
+} ;
+
+
+/*******************************************************************
+
+ NAME: SetEverybodyPermission
+
+ SYNOPSIS: Set the registry key to everybody "Set Value" (or whatever
+ the caller want.) This is called from the inf file
+
+ ENTRY: Registry key as the first parameter
+ Permisstion type as the second parameter
+
+ RETURN: BOOL - TRUE for success.
+
+ HISTORY:
+ terryk 07-May-1993 Created
+
+********************************************************************/
+
+typedef DWORD (*T_SetPermission)(HKEY hKey, DWORD dwPermission);
+
+BOOL FAR PASCAL SetEverybodyPermission( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ HKEY hKey = (HKEY)atol( &(apszArgs[0][1]) ); // registry key
+ DWORD dwPermission = atol( apszArgs[1] ); // permission value
+ DWORD err = ERROR_SUCCESS;
+
+ do {
+ HINSTANCE hDll = LoadLibraryA( "nwapi32.dll" );
+ FARPROC pSetPermission = NULL;
+
+ if ( hDll == NULL )
+ {
+ err = GetLastError();
+ break;
+ }
+
+ pSetPermission = GetProcAddress( hDll, "NwLibSetEverybodyPermission" );
+
+ if ( pSetPermission == NULL )
+ {
+ err = GetLastError();
+ break;
+ }
+ err = (*(T_SetPermission)pSetPermission)( hKey, dwPermission );
+ } while ( FALSE );
+
+ wsprintfA( achBuff, "{\"%d\"}", err );
+ *ppszResult = achBuff;
+
+ return( err == ERROR_SUCCESS );
+}
+
+/*******************************************************************
+
+ NAME: SetFileSysChangeValue
+
+ SYNOPSIS: calls common setup routine. this old entry point is
+ is left here to handle any DLL/INF mismatch.
+
+ ENTRY: NONE from inf file.
+
+ RETURN: BOOL - TRUE for success.
+ (always return TRUE)
+
+ HISTORY:
+ chuckc 29-Oct-1993 Created
+
+********************************************************************/
+
+BOOL FAR PASCAL SetFileSysChangeValue( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ return SetupRegistryWorker( nArgs, apszArgs, ppszResult );
+}
+
+/*******************************************************************
+
+ NAME: SetupRegistryForNWCS
+
+ SYNOPSIS: calls common worker routine to setup registry.
+
+ ENTRY: NONE from inf file.
+
+ RETURN: BOOL - TRUE for success.
+ (always return TRUE)
+
+ HISTORY:
+ chuckc 29-Oct-1993 Created
+
+********************************************************************/
+
+BOOL FAR PASCAL SetupRegistryForNWCS( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ return SetupRegistryWorker( nArgs, apszArgs, ppszResult );
+}
+
+/*******************************************************************
+
+ NAME: SetupRegistryWorker
+
+ SYNOPSIS: set the FileSysChangeValue to please NETWARE.DRV.
+ also set win.ini parameter so wfwnet.drv knows we are there.
+
+ ENTRY: NONE from inf file.
+
+ RETURN: BOOL - TRUE for success.
+ (always return TRUE)
+
+ HISTORY:
+ chuckc 29-Oct-1993 Created
+
+********************************************************************/
+
+BOOL FAR PASCAL SetupRegistryWorker( DWORD nArgs, LPSTR apszArgs[], LPSTR * ppszResult )
+{
+ DWORD err = 0, err1 = 0 ;
+
+ (void) nArgs ; // quiet the compiler
+ (void) apszArgs ; // quiet the compiler
+
+ if (!WriteProfileStringA("NWCS",
+ "NwcsInstalled",
+ "1"))
+ {
+ err = GetLastError() ;
+ }
+
+ if (!WritePrivateProfileStringA("386Enh",
+ "FileSysChange",
+ "off",
+ "system.ini"))
+ {
+ err1 = GetLastError() ;
+ }
+
+ if (err1 == NO_ERROR)
+ {
+ err1 = SetupShellExtensions(
+ RegCreateEntries,
+ sizeof(RegCreateEntries)/sizeof(RegCreateEntries[0])) ;
+ }
+
+ wsprintfA( achBuff, "{\"%d\"}", err ? err : err1 );
+ *ppszResult = achBuff;
+
+ return TRUE;
+}
+
+#define NWCLEANUPGATEWAYSHARES_NAME "NwCleanupGatewayShares"
+#define NWPROVAU_DLL_NAME L"NWPROVAU"
+
+/*******************************************************************
+
+ NAME: DeleteGatewayPassword
+
+ SYNOPSIS: delete the LSA secret used for gateway password.
+ also clears the NWCS installed bit. INF will be
+ changed to call CleanupRegistryForNWCS, but this entry
+ point is left here to handle DLL/INF mismatch.
+
+ ENTRY: NONE from inf file.
+
+ RETURN: BOOL - TRUE for success.
+ (always return TRUE)
+
+ HISTORY:
+ chuckc 29-Oct-1993 Created
+
+********************************************************************/
+
+BOOL FAR PASCAL
+DeleteGatewayPassword(
+ DWORD nArgs,
+ LPSTR apszArgs[],
+ LPSTR * ppszResult
+ )
+{
+ return TRUE ; // work is done in cleanup below which does everything.
+}
+
+/*******************************************************************
+
+ NAME: CleanupRegistryForNWCS
+
+ SYNOPSIS: delete the LSA secret used for gateway password.
+ also set flag that NWCS has been removed. this flag
+ is used by wfwnet.drv.
+
+ ENTRY: NONE from inf file.
+
+ RETURN: BOOL - TRUE for success.
+ (always return TRUE)
+
+ HISTORY:
+ chuckc 29-Oct-1993 Created
+
+********************************************************************/
+
+BOOL FAR PASCAL
+CleanupRegistryForNWCS(
+ DWORD nArgs,
+ LPSTR apszArgs[],
+ LPSTR * ppszResult
+ )
+{
+ HANDLE hDll ;
+ DWORD err = 0, err1 = 0 ;
+ LPNWCLEANUPGATEWAYSHARES lpfnNwCleanupGatewayShares = NULL ;
+
+ (void) nArgs ; // quiet the compiler
+ (void) apszArgs ; // quiet the compiler
+
+ if (!WriteProfileStringA("NWCS",
+ "NwcsInstalled",
+ "0"))
+ {
+ err = GetLastError() ;
+ }
+
+ err1 = NwDeletePassword(GATEWAY_USER) ;
+
+ if (!err)
+ err = err1 ;
+
+ if ((hDll = LoadLibraryW(NWPROVAU_DLL_NAME)) &&
+ (lpfnNwCleanupGatewayShares = (LPNWCLEANUPGATEWAYSHARES)
+ GetProcAddress(hDll, NWCLEANUPGATEWAYSHARES_NAME)))
+ {
+ err1 = (*lpfnNwCleanupGatewayShares)() ;
+ (void) FreeLibrary(hDll) ;
+ }
+
+ //
+ // ignore errors for this.
+ //
+ (void) SetupShellExtensions(
+ RegDeleteEntries,
+ sizeof(RegDeleteEntries)/sizeof(RegDeleteEntries[0])) ;
+
+ if (!err)
+ err = err1 ;
+
+ wsprintfA( achBuff, "{\"%d\"}", err );
+ *ppszResult = achBuff;
+
+ return TRUE;
+}
+
+/*******************************************************************
+
+ NAME: SetupShellExtensions
+
+ SYNOPSIS: setup the registry for shell extensions. function is driven
+ by a table of entries (RegEntries). for each entry there is a
+ Operation code that tells us what we are doing. key entries can
+ be created absolute or relative to previous positions, so we
+ maintain a stack of registry handles for the latter case. every
+ key that is created is initially put on the stack. values
+ are always written based on the 'current stack' position.
+
+ ENTRY: NONE
+
+ RETURN: Win32 error code
+
+ HISTORY:
+ chuckc 29-Nov-1995 Created
+
+********************************************************************/
+DWORD SetupShellExtensions(REG_ENTRY RegEntries[], DWORD dwNumEntries)
+{
+ DWORD err, errClose, dwDisposition, i ;
+ HKEY hKey, RegHandleStack[MAX_REG_LEVEL] ;
+ LONG StackIndex = -1 ;
+
+ //
+ // Loop thru and for each entry. Then switch & do the appropriate
+ // operation in the registry.
+ //
+
+ for (i = 0; i < dwNumEntries; i++)
+ {
+ err = NO_ERROR ;
+
+ switch (RegEntries[i].Operation)
+ {
+ case CREATE_ABS:
+
+ //
+ // create/open a reg key with an absolute path. since this
+ // is absolute, we drop everything on the stack, and start
+ // all over again.
+ //
+
+ while (StackIndex >= 0)
+ {
+ errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
+ ASSERT(errClose == NO_ERROR) ;
+ }
+
+ err = RegCreateKeyExW(HKEY_LOCAL_MACHINE,
+ RegEntries[i].s1, // subkey
+ 0, // reserved
+ NULL, // class
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL, // default security
+ &hKey,
+ &dwDisposition) ; // not used
+ if (err != NO_ERROR)
+ {
+ break ;
+ }
+
+ //
+ // by default we advance the stack. no need check for overflow
+ // as the stack is empty.
+ //
+
+ RegHandleStack[++StackIndex] = hKey ;
+ break ;
+
+ case CREATE_REL:
+
+ //
+ // create/open a reg key relative to current stack. make sure
+ // there is something on the stack (check StackIndex >= 0).
+ // then see if we are advancing (+1), staying the same (0) or
+ // dropping back (-ve).
+ //
+
+ if (StackIndex < 0)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ if (RegEntries[i].Level == +1)
+ {
+ //
+ // opening next level down. continue as is and use
+ // most recently opened key as the starting point.
+ //
+ }
+ else if (RegEntries[i].Level == 0)
+ {
+ //
+ // opening at same level as last time. so we are done
+ // with the last key. what we want to do is close it
+ // and use the parent.
+ //
+ errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
+
+ ASSERT(errClose == NO_ERROR) ;
+
+ if (StackIndex < 0)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+ }
+ else if (RegEntries[i].Level < 0)
+ {
+ //
+ // dropping back & opening at a higher level. cleanup
+ // handle for each level we pop.
+ //
+
+ LONG Count = RegEntries[i].Level ;
+
+ while (Count++ < 1)
+ {
+ errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
+
+ ASSERT(errClose == NO_ERROR) ;
+
+ if (StackIndex < -1)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+ }
+ }
+ else
+ {
+ //
+ // only -ve numbers, 0 and 1 are valid
+ //
+
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ //
+ // create key relative to current point
+ //
+ err = RegCreateKeyExW(RegHandleStack[StackIndex], // current key
+ RegEntries[i].s1, // subkey
+ 0, // reserved
+ NULL, // class
+ REG_OPTION_NON_VOLATILE,
+ KEY_ALL_ACCESS,
+ NULL, // default security
+ &hKey,
+ &dwDisposition) ; // not used
+ if (err != NO_ERROR)
+ {
+ break ;
+ }
+
+ //
+ // by default we advance the stack
+ //
+
+ RegHandleStack[++StackIndex] = hKey ;
+
+ if (StackIndex >= MAX_REG_LEVEL)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ break ;
+
+ case VALUE_STR:
+
+ //
+ // create a REG_SZ value at current point. check we have
+ // handle on stack.
+ //
+
+ if (StackIndex < 0)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ err = RegSetValueExW(
+ RegHandleStack[StackIndex], // current key
+ RegEntries[i].s1, // value name
+ 0, // reserved
+ REG_SZ,
+ (BYTE *)RegEntries[i].s2, // value data
+ (wcslen(RegEntries[i].s2)+1)*sizeof(WCHAR)) ;
+ break ;
+
+ case DELETE_ABS:
+
+ //
+ // delete a key (absolute). no change to stack.
+ //
+
+ err = RegDeleteKeyW(HKEY_LOCAL_MACHINE,
+ RegEntries[i].s1) ; // subkey
+
+ if ( err == ERROR_FILE_NOT_FOUND )
+ err = NO_ERROR;
+
+ break ;
+
+ case DELETE_REL:
+
+ //
+ // delete a key (relative). no change to stack.
+ //
+
+ if (StackIndex < 0)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ err = RegDeleteKeyW(RegHandleStack[StackIndex], // current key
+ RegEntries[i].s1) ; // subkey
+
+ if ( err == ERROR_FILE_NOT_FOUND )
+ err = NO_ERROR;
+
+ break ;
+
+ case DELETE_VAL:
+
+ //
+ // delete value at current point. check we have handle on stack.
+ //
+
+ if (StackIndex < 0)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ err = RegDeleteValueW(RegHandleStack[StackIndex], // current key
+ RegEntries[i].s1) ; // value name
+ break ;
+
+ case DROP_STACK:
+
+ //
+ // drop current stack by one (closing the handle).
+ //
+
+ if (StackIndex < 0)
+ {
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
+
+ ASSERT(errClose == NO_ERROR) ;
+
+ break ;
+
+ default:
+
+ //
+ // error out if unknown operation
+ //
+
+ err = ERROR_INVALID_FUNCTION ;
+ break ;
+ }
+
+ if (err != NO_ERROR)
+ {
+ break ;
+ }
+ }
+
+ //
+ // cleanup open handles on the stack
+ //
+
+ while (StackIndex >= 0)
+ {
+ errClose = RegCloseKey(RegHandleStack[StackIndex--]) ;
+ ASSERT(errClose == NO_ERROR) ;
+ }
+
+ return err ;
+}
diff --git a/private/nw/install/setupdll/sources b/private/nw/install/setupdll/sources
new file mode 100644
index 000000000..81943eec1
--- /dev/null
+++ b/private/nw/install/setupdll/sources
@@ -0,0 +1,48 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1989
+
+!ENDIF
+
+MAJORCOMP=shell
+MINORCOMP=library
+
+INCLUDES=.;..\..\svcdlls\nwwks\inc;..\..\inc
+MSC_WARNING_LEVEL=/W3 /WX
+
+TARGETNAME=nwcfg
+TARGETPATH=obj
+TARGETTYPE=DYNLINK
+UMTYPE=windows
+
+TARGETLIBS= $(BASEDIR)\public\sdk\lib\*\user32.lib \
+ $(BASEDIR)\public\sdk\lib\*\advapi32.lib \
+ $(BASEDIR)\public\sdk\lib\*\kernel32.lib \
+ ..\..\svcdlls\nwwks\lib\obj\*\nwwlib.lib
+
+DLLBASE=0x67800000
+DLLENTRY=DLLInit
+SOURCES=nwcfg.cxx \
+ removesz.c \
+ setvalue.c \
+ lodctr.c \
+ unlodctr.c \
+ dllinit.c \
+ nwcfg.rc
+
diff --git a/private/nw/install/setupdll/unlodctr.c b/private/nw/install/setupdll/unlodctr.c
new file mode 100644
index 000000000..0a9dc1c13
--- /dev/null
+++ b/private/nw/install/setupdll/unlodctr.c
@@ -0,0 +1,1006 @@
+/*++
+
+Copyright (c) 1991-1993 Microsoft Corporation
+
+Module Name:
+
+ unlodctr.c
+
+Abstract:
+
+ Program to remove the counter names belonging to the driver specified
+ in the command line and update the registry accordingly
+
+Author:
+
+ Bob Watson (a-robw) 12 Feb 93
+
+Revision History:
+
+--*/
+#define UNICODE 1
+#define _UNICODE 1
+//
+// "C" Include files
+//
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <malloc.h>
+//
+// Windows Include files
+//
+#include <windows.h>
+#include <winperf.h>
+#include <tchar.h>
+//
+// local include files
+//
+//#define _INITIALIZE_GLOBALS_ 1 // to define & init global buffers
+#include "common.h"
+//#undef _INITIALIZE_GLOBALS_
+#include "nwcfg.hxx"
+
+// version number for NT 1.0
+#define OLD_VERSION 0x010000
+DWORD dwSystemVersion; // PerfLib version number
+DWORD dwHelpItems; // number of explain text items
+DWORD dwCounterItems; // number of counter text items
+DWORD dwLastCounter;
+DWORD dwLastHelp;
+
+
+LPTSTR
+*BuildNameTable(
+ IN HKEY hKeyPerflib, // handle to perflib key with counter names
+ IN LPTSTR lpszLangId, // unicode value of Language subkey
+ OUT PDWORD pdwLastItem, // size of array in elements
+ OUT HKEY *hKeyNames,
+ OUT LPTSTR CounterNameBuffer, // New version counter name key
+ OUT LPTSTR HelpNameBuffer // New version help name key
+)
+/*++
+
+BuildNameTable
+
+ Caches the counter names and explain text to accelerate name lookups
+ for display.
+
+Arguments:
+
+ hKeyPerflib
+ Handle to an open registry (this can be local or remote.) and
+ is the value returned by RegConnectRegistry or a default key.
+
+ lpszLangId
+ The unicode id of the language to look up. (default is 009)
+
+ pdwLastItem
+ The last array element
+
+Return Value:
+
+ pointer to an allocated table. (the caller must free it when finished!)
+ the table is an array of pointers to zero terminated TEXT strings.
+
+ A NULL pointer is returned if an error occured. (error value is
+ available using the GetLastError function).
+
+ The structure of the buffer returned is:
+
+ Array of pointers to zero terminated strings consisting of
+ pdwLastItem elements
+
+ MULTI_SZ string containing counter id's and names returned from
+ registry for the specified language
+
+ MULTI_SZ string containing explain text id's and explain text strings
+ as returned by the registry for the specified language
+
+ The structures listed above are contiguous so that they may be freed
+ by a single "free" call when finished with them, however only the
+ array elements are intended to be used.
+
+--*/
+{
+
+ LPTSTR *lpReturnValue; // returned pointer to buffer
+
+ LPTSTR *lpCounterId; //
+ LPTSTR lpCounterNames; // pointer to Names buffer returned by reg.
+ LPTSTR lpHelpText ; // pointet to exlpain buffer returned by reg.
+
+ LPTSTR lpThisName; // working pointer
+
+
+ BOOL bStatus; // return status from TRUE/FALSE fn. calls
+ LONG lWin32Status; // return status from fn. calls
+
+ DWORD dwValueType; // value type of buffer returned by reg.
+ DWORD dwArraySize; // size of pointer array in bytes
+ DWORD dwBufferSize; // size of total buffer in bytes
+ DWORD dwCounterSize; // size of counter text buffer in bytes
+ DWORD dwHelpSize; // size of help text buffer in bytes
+ DWORD dwThisCounter; // working counter
+
+ DWORD dwLastId; // largest ID value used by explain/counter text
+
+ LPTSTR lpValueNameString; // pointer to buffer conatining subkey name
+
+ //initialize pointers to NULL
+
+ lpValueNameString = NULL;
+ lpReturnValue = NULL;
+
+ // check for null arguments and insert defaults if necessary
+
+ if (!lpszLangId) {
+ lpszLangId = DefaultLangId;
+ }
+
+ if (hKeyNames) {
+ *hKeyNames = NULL;
+ } else {
+ SetLastError (ERROR_BAD_ARGUMENTS);
+ return NULL;
+ }
+
+ // use the greater of Help items or Counter Items to size array
+
+ if (dwHelpItems >= dwCounterItems) {
+ dwLastId = dwHelpItems;
+ } else {
+ dwLastId = dwCounterItems;
+ }
+
+ // array size is # of elements (+ 1, since names are "1" based)
+ // times the size of a pointer
+
+ dwArraySize = (dwLastId + 1) * sizeof(LPTSTR);
+
+ // allocate string buffer for language ID key string
+
+ lpValueNameString = malloc (
+ lstrlen(NamesKey) * sizeof (TCHAR) +
+ lstrlen(Slash) * sizeof (TCHAR) +
+ lstrlen(lpszLangId) * sizeof (TCHAR) +
+ sizeof (TCHAR));
+
+ if (!lpValueNameString) {
+ lWin32Status = ERROR_OUTOFMEMORY;
+ goto BNT_BAILOUT;
+ }
+
+ lWin32Status = RegOpenKeyEx ( // get handle to this key in the
+ hKeyPerflib, // registry
+ lpszLangId,
+ RESERVED,
+ KEY_READ | KEY_WRITE,
+ hKeyNames);
+
+ if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
+
+ // get size of counter names
+
+ dwBufferSize = 0;
+ lWin32Status = RegQueryValueEx (
+ *hKeyNames,
+ Counters,
+ RESERVED,
+ &dwValueType,
+ NULL,
+ &dwBufferSize);
+
+ if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
+
+ dwCounterSize = dwBufferSize;
+
+ // get size of help text
+
+ dwBufferSize = 0;
+ lWin32Status = RegQueryValueEx (
+ *hKeyNames,
+ Help,
+ RESERVED,
+ &dwValueType,
+ NULL,
+ &dwBufferSize);
+
+ if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
+
+ dwHelpSize = dwBufferSize;
+
+ // allocate buffer with room for pointer array, counter name
+ // strings and help name strings
+
+ lpReturnValue = malloc (dwArraySize + dwCounterSize + dwHelpSize);
+
+ if (!lpReturnValue) {
+ lWin32Status = ERROR_OUTOFMEMORY;
+ goto BNT_BAILOUT;
+ }
+
+ // initialize buffer
+
+ memset (lpReturnValue, 0, _msize(lpReturnValue));
+
+ // initialize pointers into buffer
+
+ lpCounterId = lpReturnValue;
+ lpCounterNames = (LPTSTR)((LPBYTE)lpCounterId + dwArraySize);
+ lpHelpText = (LPTSTR)((LPBYTE)lpCounterNames + dwCounterSize);
+
+ // read counter names into buffer. Counter names will be stored as
+ // a MULTI_SZ string in the format of "###" "Name"
+
+ dwBufferSize = dwCounterSize;
+ lWin32Status = RegQueryValueEx (
+ *hKeyNames,
+ Counters,
+ RESERVED,
+ &dwValueType,
+ (LPVOID)lpCounterNames,
+ &dwBufferSize);
+
+ if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
+
+ // read explain text into buffer. Counter names will be stored as
+ // a MULTI_SZ string in the format of "###" "Text..."
+
+ dwBufferSize = dwHelpSize;
+ lWin32Status = RegQueryValueEx (
+ *hKeyNames,
+ Help,
+ RESERVED,
+ &dwValueType,
+ (LPVOID)lpHelpText,
+ &dwBufferSize);
+
+ if (lWin32Status != ERROR_SUCCESS) goto BNT_BAILOUT;
+
+ // load counter array items, by locating each text string
+ // in the returned buffer and loading the
+ // address of it in the corresponding pointer array element.
+
+ for (lpThisName = lpCounterNames;
+ *lpThisName;
+ lpThisName += (lstrlen(lpThisName)+1) ) {
+
+ // first string should be an integer (in decimal digit characters)
+ // so translate to an integer for use in array element identification
+
+ bStatus = StringToInt (lpThisName, &dwThisCounter);
+
+ if (!bStatus) {
+ // error is in GetLastError
+ goto BNT_BAILOUT; // bad entry
+ }
+
+ // point to corresponding counter name which follows the id number
+ // string.
+
+ lpThisName += (lstrlen(lpThisName)+1);
+
+ // and load array element with pointer to string
+
+ lpCounterId[dwThisCounter] = lpThisName;
+
+ }
+
+ // repeat the above for the explain text strings
+
+ for (lpThisName = lpHelpText;
+ *lpThisName;
+ lpThisName += (lstrlen(lpThisName)+1) ) {
+
+ // first string should be an integer (in decimal unicode digits)
+
+ bStatus = StringToInt (lpThisName, &dwThisCounter);
+
+ if (!bStatus) {
+ // error is in GetLastError
+ goto BNT_BAILOUT; // bad entry
+ }
+
+ // point to corresponding counter name
+
+ lpThisName += (lstrlen(lpThisName)+1);
+
+ // and load array element;
+
+ lpCounterId[dwThisCounter] = lpThisName;
+
+ }
+
+ // if the last item arugment was used, then load the last ID value in it
+
+ if (pdwLastItem) *pdwLastItem = dwLastId;
+
+ // free the temporary buffer used
+
+ if (lpValueNameString) {
+ free ((LPVOID)lpValueNameString);
+ }
+
+ // exit returning the pointer to the buffer
+
+ return lpReturnValue;
+
+BNT_BAILOUT:
+ if (lWin32Status != ERROR_SUCCESS) {
+ // if lWin32Status has error, then set last error value to it,
+ // otherwise assume that last error already has value in it
+ SetLastError (lWin32Status);
+ }
+
+ // free buffers used by this routine
+
+ if (lpValueNameString) {
+ free ((LPVOID)lpValueNameString);
+ }
+
+ if (lpReturnValue) {
+ free ((LPVOID)lpReturnValue);
+ }
+
+ return NULL;
+} // BuildNameTable
+
+
+BOOL
+GetDriverFromCommandLine (
+ HKEY hKeyMachine,
+ LPTSTR *lpDriverName,
+ HKEY *hDriverPerf,
+ LPSTR argv[]
+)
+/*++
+
+GetDriverFromCommandLine
+
+ locates the first argument in the command line string (after the
+ image name) and checks to see if
+
+ a) it's there
+
+ b) it's the name of a device driver listed in the
+ Registry\Machine\System\CurrentControlSet\Services key
+ in the registry and it has a "Performance" subkey
+
+ c) that the "First Counter" value under the Performance subkey
+ is defined.
+
+ if all these criteria are true, then the routine returns TRUE and
+ passes the pointer to the driver name back in the argument. If any
+ one of them fail, then NULL is returned in the DriverName arg and
+ the routine returns FALSE
+
+Arguments
+
+ lpDriverName
+
+ the address of a LPTSTR to recive the pointer to the driver name
+
+ hDriverPerf
+
+ the key to the driver's performance subkey
+
+Return Value
+
+ TRUE if a valid driver was found in the command line
+
+ FALSE if not (see above)
+
+--*/
+{
+ LPTSTR lpDriverKey; // buffer to build driver key name in
+ LPTSTR lpThisChar;
+
+ LONG lStatus;
+ DWORD dwFirstCounter;
+ DWORD dwSize;
+ DWORD dwType;
+
+ if (!lpDriverName || !hDriverPerf) {
+ SetLastError (ERROR_BAD_ARGUMENTS);
+ return FALSE;
+ }
+
+ *lpDriverName = NULL; // initialize to NULL
+ *hDriverPerf = NULL;
+
+ lpThisChar = malloc( MAX_PATH * sizeof(TCHAR));
+ MultiByteToWideChar( CP_ACP, MB_PRECOMPOSED, argv[0], -1, lpThisChar, MAX_PATH);
+
+ if (*lpThisChar) {
+ // an argument was found so see if it's a driver
+ lpDriverKey = malloc (MAX_PATH * sizeof (TCHAR));
+ if (!lpDriverKey) {
+ SetLastError (ERROR_OUTOFMEMORY);
+ if ( lpThisChar ) free (lpThisChar);
+ return FALSE;
+ }
+
+ lstrcpy (lpDriverKey, DriverPathRoot);
+ lstrcat (lpDriverKey, Slash);
+ lstrcat (lpDriverKey, lpThisChar);
+ lstrcat (lpDriverKey, Slash);
+ lstrcat (lpDriverKey, Performance);
+
+ lStatus = RegOpenKeyEx (
+ hKeyMachine,
+ lpDriverKey,
+ RESERVED,
+ KEY_READ | KEY_WRITE,
+ hDriverPerf);
+
+ if (lStatus == ERROR_SUCCESS) {
+ //
+ // this driver has a performance section so see if its
+ // counters are installed by checking the First Counter
+ // value key for a valid return. If it returns a value
+ // then chances are, it has some counters installed, if
+ // not, then display a message and quit.
+ //
+ free (lpDriverKey); // don't need this any more
+
+ dwType = 0;
+ dwSize = sizeof (dwFirstCounter);
+
+ lStatus = RegQueryValueEx (
+ *hDriverPerf,
+ FirstCounter,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwFirstCounter,
+ &dwSize);
+
+ if (lStatus == ERROR_SUCCESS) {
+ // counter names are installed so return success
+ *lpDriverName = lpThisChar;
+ SetLastError (ERROR_SUCCESS);
+ if ( lpThisChar ) free (lpThisChar);
+ return TRUE;
+ } else {
+ SetLastError (ERROR_BADKEY);
+ if ( lpThisChar ) free (lpThisChar);
+ return FALSE;
+ }
+ } else { // key not found
+ SetLastError (lStatus);
+ free (lpDriverKey);
+ if ( lpThisChar ) free (lpThisChar);
+ return FALSE;
+ }
+ } else {
+ SetLastError (ERROR_INVALID_PARAMETER);
+ if ( lpThisChar ) free (lpThisChar);
+ return FALSE;
+ }
+}
+
+
+LONG
+FixNames (
+ HANDLE hKeyLang,
+ LPTSTR *lpOldNameTable,
+ IN LPTSTR lpszLangId, // unicode value of Language subkey
+ DWORD dwLastItem,
+ DWORD dwFirstNameToRemove,
+ DWORD dwLastNameToRemove
+ )
+{
+ LONG lStatus;
+ LPTSTR lpNameBuffer = NULL;
+ LPTSTR lpHelpBuffer = NULL;
+ DWORD dwTextIndex, dwSize;
+ LPTSTR lpNextHelpText;
+ LPTSTR lpNextNameText;
+
+ // allocate space for the array of new text it will point
+ // into the text buffer returned in the lpOldNameTable buffer)
+
+ lpNameBuffer = malloc (_msize(lpOldNameTable));
+ lpHelpBuffer = malloc (_msize(lpOldNameTable));
+
+ if (!lpNameBuffer || !lpHelpBuffer) {
+ lStatus = ERROR_OUTOFMEMORY;
+ return lStatus;
+ }
+
+ // remove this driver's counters from array
+
+ for (dwTextIndex = dwFirstNameToRemove;
+ dwTextIndex <= dwLastNameToRemove;
+ dwTextIndex++) {
+
+ if (dwTextIndex > dwLastItem)
+ break;
+
+ lpOldNameTable[dwTextIndex] = NULL;
+ }
+
+ lpNextHelpText = lpHelpBuffer;
+ lpNextNameText = lpNameBuffer;
+
+ // build new Multi_SZ strings from New Table
+
+ for (dwTextIndex = 0; dwTextIndex <= dwLastItem; dwTextIndex++){
+ if (lpOldNameTable[dwTextIndex]) {
+ // if there's a text string at that index, then ...
+ if (dwTextIndex & 0x1) { // ODD number == Help Text
+ lpNextHelpText +=
+ _stprintf (lpNextHelpText, TEXT("%d"), dwTextIndex) + 1;
+ lpNextHelpText +=
+ _stprintf (lpNextHelpText, TEXT("%s"),
+ lpOldNameTable[dwTextIndex]) + 1;
+ if (dwTextIndex > dwLastHelp){
+ dwLastHelp = dwTextIndex;
+ }
+ } else { // EVEN number == counter name text
+ lpNextNameText +=
+ _stprintf (lpNextNameText, TEXT("%d"), dwTextIndex) + 1;
+ lpNextNameText +=
+ _stprintf (lpNextNameText, TEXT("%s"),
+ lpOldNameTable[dwTextIndex]) + 1;
+ if (dwTextIndex > dwLastCounter){
+ dwLastCounter = dwTextIndex;
+ }
+ }
+ }
+ } // for dwTextIndex
+
+ // add MULTI_SZ terminating NULL
+ *lpNextNameText++ = TEXT ('\0');
+ *lpNextHelpText++ = TEXT ('\0');
+
+ // update counter name text buffer
+
+ dwSize = (DWORD)((LPBYTE)lpNextNameText - (LPBYTE)lpNameBuffer);
+ lStatus = RegSetValueEx (
+ hKeyLang,
+ Counters,
+ RESERVED,
+ REG_MULTI_SZ,
+ (LPBYTE)lpNameBuffer,
+ dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+// printf (GetFormatResource(UC_UNABLELOADLANG),
+// Counters, lpLangName, lStatus);
+ goto UCN_FinishLang;
+ }
+
+ dwSize = (DWORD)((LPBYTE)lpNextHelpText - (LPBYTE)lpHelpBuffer);
+ lStatus = RegSetValueEx (
+ hKeyLang,
+ Help,
+ RESERVED,
+ REG_MULTI_SZ,
+ (LPBYTE)lpHelpBuffer,
+ dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+// printf (GetFormatResource(UC_UNABLELOADLANG),
+// Help, lpLangName, lStatus);
+ goto UCN_FinishLang;
+ }
+
+
+UCN_FinishLang:
+
+ free (lpNameBuffer);
+ free (lpHelpBuffer);
+ free (lpOldNameTable);
+
+ RegCloseKey (hKeyLang);
+
+ return lStatus;
+}
+
+LONG
+UnloadCounterNames (
+ HKEY hKeyMachine,
+ HKEY hDriverPerf,
+ LPTSTR lpDriverName
+)
+/*++
+
+UnloadCounterNames
+
+ removes the names and explain text for the driver referenced by
+ hDriverPerf and updates the first and last counter values accordingly
+
+ update process:
+
+ - set "updating" flag under Perflib to name of driver being modified
+ - FOR each language under perflib key
+ -- load current counter names and explain text into array of
+ pointers
+ -- look at all drivers and copy their names and text into a new
+ buffer adjusting for the removed counter's entries keeping
+ track of the lowest entry copied. (the names for the driver
+ to be removed will not be copied, of course)
+ -- update each driver's "first" and "last" index values
+ -- copy all other entries from 0 to the lowest copied (i.e. the
+ system counters)
+ -- build a new MULIT_SZ string of help text and counter names
+ -- load new strings into registry
+ - update perflibl "last" counters
+ - delete updating flag
+
+ ******************************************************
+ * *
+ * NOTE: FUNDAMENTAL ASSUMPTION..... *
+ * *
+ * this routine assumes that: *
+ * *
+ * ALL COUNTER NAMES are even numbered and *
+ * ALL HELP TEXT STRINGS are odd numbered *
+ * *
+ ******************************************************
+
+Arguments
+
+ hKeyMachine
+
+ handle to HKEY_LOCAL_MACHINE node of registry on system to
+ remove counters from
+
+ hDrivefPerf
+ handle to registry key of driver to be de-installed
+
+ lpDriverName
+ name of driver being de-installed
+
+Return Value
+
+ DOS Error code.
+
+ ERROR_SUCCESS if all went OK
+ error value if not.
+
+--*/
+{
+
+ HKEY hPerflib;
+ HKEY hServices;
+ HKEY hKeyLang;
+
+ LONG lStatus;
+
+ DWORD dwLangIndex;
+ DWORD dwSize;
+ DWORD dwType;
+ DWORD dwLastItem;
+
+
+ DWORD dwRemLastDriverCounter;
+ DWORD dwRemFirstDriverCounter;
+ DWORD dwRemLastDriverHelp;
+ DWORD dwRemFirstDriverHelp;
+
+ DWORD dwFirstNameToRemove;
+ DWORD dwLastNameToRemove;
+
+ LPTSTR *lpOldNameTable;
+
+ LPTSTR lpLangName = NULL;
+ LPTSTR lpThisDriver = NULL;
+
+ BOOL bPerflibUpdated = FALSE;
+ BOOL bDriversShuffled = FALSE;
+
+ DWORD dwBufferSize; // size of total buffer in bytes
+
+ TCHAR CounterNameBuffer [40];
+ TCHAR HelpNameBuffer [40];
+
+ lStatus = RegOpenKeyEx (
+ hKeyMachine,
+ DriverPathRoot,
+ RESERVED,
+ KEY_READ | KEY_WRITE,
+ &hServices);
+
+ if (lStatus != ERROR_SUCCESS) {
+ return lStatus;
+ }
+
+ // open registry handle to perflib key
+
+ lStatus = RegOpenKeyEx (
+ hKeyMachine,
+ NamesKey,
+ RESERVED,
+ KEY_READ | KEY_WRITE,
+ &hPerflib);
+
+ if (lStatus != ERROR_SUCCESS) {
+ return lStatus;
+ }
+
+ // check & set Busy flag...
+
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ Busy,
+ RESERVED,
+ &dwType,
+ NULL,
+ &dwSize);
+
+ if (lStatus == ERROR_SUCCESS) { // perflib is in use at the moment
+ return ERROR_BUSY;
+ }
+
+
+ lStatus = RegSetValueEx (
+ hPerflib,
+ Busy,
+ RESERVED,
+ REG_SZ,
+ (LPBYTE)lpDriverName,
+ lstrlen(lpDriverName) * sizeof(TCHAR));
+
+ if (lStatus != ERROR_SUCCESS) {
+ RegCloseKey (hPerflib);
+ return lStatus;
+ }
+
+ // query registry to get number of Explain text items
+
+ dwBufferSize = sizeof (dwHelpItems);
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ LastHelp,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwHelpItems,
+ &dwBufferSize);
+
+ if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
+ RegCloseKey (hPerflib);
+ return lStatus;
+ }
+
+ // query registry to get number of counter and object name items
+
+ dwBufferSize = sizeof (dwCounterItems);
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ LastCounter,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwCounterItems,
+ &dwBufferSize);
+
+ if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
+ RegCloseKey (hPerflib);
+ return lStatus;
+ }
+
+ // query registry to get PerfLib system version
+
+ dwBufferSize = sizeof (dwSystemVersion);
+ lStatus = RegQueryValueEx (
+ hPerflib,
+ VersionStr,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwSystemVersion,
+ &dwBufferSize);
+
+ if ((lStatus != ERROR_SUCCESS) || (dwType != REG_DWORD)) {
+ // Key not there, must be NT 1.0 version
+ dwSystemVersion = OLD_VERSION;
+ }
+
+ if ( dwSystemVersion != OLD_VERSION )
+ {
+ // ERROR. The caller should check the version before calling me.
+ // let return busy for now...
+ return(ERROR_BUSY);
+ }
+
+
+ // allocate temporary String buffer
+
+ lpLangName = malloc (MAX_PATH * sizeof(TCHAR));
+ lpThisDriver = malloc (MAX_PATH * sizeof(TCHAR));
+
+ if (!lpLangName || !lpThisDriver) {
+ lStatus = ERROR_OUTOFMEMORY;
+ goto UCN_ExitPoint;
+ }
+
+ // Get the values that are in use by the driver to be removed
+
+ dwSize = sizeof (dwRemLastDriverCounter);
+ lStatus = RegQueryValueEx (
+ hDriverPerf,
+ LastCounter,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwRemLastDriverCounter,
+ &dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ goto UCN_ExitPoint;
+ }
+
+ dwSize = sizeof (dwRemFirstDriverCounter);
+ lStatus = RegQueryValueEx (
+ hDriverPerf,
+ FirstCounter,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwRemFirstDriverCounter,
+ &dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ goto UCN_ExitPoint;
+ }
+
+ dwSize = sizeof (dwRemLastDriverHelp);
+ lStatus = RegQueryValueEx (
+ hDriverPerf,
+ LastHelp,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwRemLastDriverHelp,
+ &dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ goto UCN_ExitPoint;
+ }
+
+ dwSize = sizeof (dwRemFirstDriverHelp);
+ lStatus = RegQueryValueEx (
+ hDriverPerf,
+ FirstHelp,
+ RESERVED,
+ &dwType,
+ (LPBYTE)&dwRemFirstDriverHelp,
+ &dwSize);
+
+ if (lStatus != ERROR_SUCCESS) {
+ goto UCN_ExitPoint;
+ }
+
+ // get the first and last counters to define block of names used
+ // by this device
+
+ dwFirstNameToRemove = (dwRemFirstDriverCounter <= dwRemFirstDriverHelp ?
+ dwRemFirstDriverCounter : dwRemFirstDriverHelp);
+
+ dwLastNameToRemove = (dwRemLastDriverCounter >= dwRemLastDriverHelp ?
+ dwRemLastDriverCounter : dwRemLastDriverHelp);
+
+ dwLastCounter = dwLastHelp = 0;
+
+ // do each language under perflib
+ for (dwLangIndex = 0, dwSize = _msize(lpLangName);
+ (RegEnumKey(hPerflib, dwLangIndex, lpLangName, dwSize)) == ERROR_SUCCESS;
+ dwLangIndex++, dwSize = _msize(lpLangName)) {
+
+ lpOldNameTable = BuildNameTable (hPerflib, lpLangName,
+ &dwLastItem, &hKeyLang, CounterNameBuffer, HelpNameBuffer);
+
+ if (lpOldNameTable) {
+ if (!FixNames (
+ hKeyLang,
+ lpOldNameTable,
+ lpLangName,
+ dwLastItem,
+ dwFirstNameToRemove,
+ dwLastNameToRemove)) {
+ bPerflibUpdated = TRUE;
+ }
+ } else { // unable to unload names for this language
+ // display error message
+ }
+ } // end for (more languages)
+
+ if (bPerflibUpdated) {
+ // update perflib's "last" values
+
+ dwSize = sizeof (dwLastCounter);
+ lStatus = RegSetValueEx (
+ hPerflib,
+ LastCounter,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwLastCounter,
+ dwSize);
+
+ dwSize = sizeof (dwLastHelp);
+ lStatus = RegSetValueEx (
+ hPerflib,
+ LastHelp,
+ RESERVED,
+ REG_DWORD,
+ (LPBYTE)&dwLastHelp,
+ dwSize);
+
+ // update "driver"s values (i.e. remove them)
+
+ RegDeleteValue (hDriverPerf, FirstCounter);
+ RegDeleteValue (hDriverPerf, LastCounter);
+ RegDeleteValue (hDriverPerf, FirstHelp);
+ RegDeleteValue (hDriverPerf, LastHelp);
+
+ }
+
+UCN_ExitPoint:
+ RegDeleteValue (hPerflib, Busy);
+ RegCloseKey (hPerflib);
+ RegCloseKey (hServices);
+ if (lpLangName) free (lpLangName);
+ if (lpThisDriver) free (lpThisDriver);
+
+ return lStatus;
+
+
+}
+
+BOOL FAR PASCAL unlodctr(DWORD argc,LPSTR argv[], LPSTR *ppszResult )
+/*++
+
+main
+
+ entry point to Counter Name Unloader
+
+
+
+Arguments
+
+ argc
+ # of command line arguments present
+
+ argv
+ array of pointers to command line strings
+
+ (note that these are obtained from the GetCommandLine function in
+ order to work with both UNICODE and ANSI strings.)
+
+ReturnValue
+
+ 0 (ERROR_SUCCESS) if command was processed
+ Non-Zero if command error was detected.
+
+--*/
+{
+ LPTSTR lpDriverName; // name of driver to delete from perflib
+ HKEY hDriverPerf; // handle to performance sub-key of driver
+
+
+ DWORD dwStatus; // return status of fn. calls
+
+ *ppszResult = achBuff;
+
+ wsprintfA( achBuff, "{\"NO_ERROR\"}");
+
+ if (!GetDriverFromCommandLine (
+ HKEY_LOCAL_MACHINE, &lpDriverName, &hDriverPerf, argv)) {
+ // error message was printed in routine if there was an error
+ wsprintfA( achBuff,"{\"ERROR\"}");
+ return (FALSE);
+ }
+
+ // removes names and explain text for driver in lpDriverName
+ // displays error messages for errors encountered
+
+ dwStatus = (DWORD)UnloadCounterNames (HKEY_LOCAL_MACHINE,
+ hDriverPerf, lpDriverName);
+
+ RegCloseKey (hDriverPerf);
+
+ if ( dwStatus != ERROR_SUCCESS )
+ {
+ wsprintfA( achBuff,"{\"ERROR\"}");
+ }
+
+ return (dwStatus==ERROR_SUCCESS);
+
+}
diff --git a/private/nw/install/wksta/alpha.txt b/private/nw/install/wksta/alpha.txt
new file mode 100644
index 000000000..a2e5c37d9
--- /dev/null
+++ b/private/nw/install/wksta/alpha.txt
@@ -0,0 +1,3 @@
+[ProductType]
+STF_PRODUCT = Winnt
+STF_PLATFORM = ALPHA
diff --git a/private/nw/install/wksta/eng.txt b/private/nw/install/wksta/eng.txt
new file mode 100644
index 000000000..0171debb2
--- /dev/null
+++ b/private/nw/install/wksta/eng.txt
@@ -0,0 +1,55 @@
+;
+; Language depended section
+;
+[OptionsWINNTTextENG]
+ NWWKSTA = "Microsoft Client Service for NetWare"
+[OptionsLANMANNTTextENG]
+ NWWKSTA = "Microsoft Gateway Service for NetWare"
+
+[WorkstationENG]
+ NWType = "Client Service for NetWare"
+[GatewayENG]
+ NWType = "Gateway Service for NetWare"
+
+[FileConstantsENG]
+NotEnoughSpace = "Out of disk space. Please remove some files before install "$(NWType)"."
+InstallNWLINKFirst = "Please install the NWLINK IPX/SPX Compatible Transport before you install the "$(NWType)"."
+InstallNTWKSTAFirst = "Please install the Windows NT Workstation service before you install the "$(NWType)"."
+RemoveAndReboot = "Please remove any existing NetWare Workstation component and reboot your machine before installing the latest version of "$(NWType)"."
+UpgradeFirst = "Please install the Windows NT patch before installing the "$(NWType)"."
+NotDaytona = "This version of "$(NWType)" does not support Windows NT 3.5."
+ProCaption = "Windows NT Setup"
+ProCancel = "Cancel"
+ProCancelMsg = "Windows NT Networking is not correctly installed. "+
+ "Are you sure you want to cancel copying files?"
+ProCancelCap = "Network Setup Message"
+ProText1 = "Copying:"
+ProText2 = "To:"
+FunctionTitle = "Workstation Services Setup"
+ProductNWWKSTADescription = $(NWType)
+ProductNWRDRDescription = "Redirector for NetWare"
+ProviderRDRName = "Redirector for NetWare"
+ProductNWWKSTATitle = $(NWType)
+ProductNWWKSTADisplayName = $(NWType)
+ProductNWRDRDisplayName = "Rdr for NetWare"
+ProductNWRDRTitle = "Redirector for NetWare"
+ProductProviderName = "NetWare Network"
+OldPrintProviderName = "NetWare(R) Network"
+
+[DialogConstantsENG]
+Help = "&Help"
+Exit = "Cancel"
+OK = "OK"
+HelpContext = ""
+Continue = "Continue"
+Cancel = "Cancel"
+ShellCodeErrorText = "Shell Code Error"
+
+[FileDependentDlgENG]
+; nothing
+
+[Source Media Descriptions]
+ 1 = "Client/Gateway Service for NetWare Disk #1" , TAGFILE = nwc.2a
+ 2 = "Client/Gateway Service for NetWare Disk #2" , TAGFILE = nwc.2b
+ 3 = ""
+
diff --git a/private/nw/install/wksta/files10.txt b/private/nw/install/wksta/files10.txt
new file mode 100644
index 000000000..1ce384d20
--- /dev/null
+++ b/private/nw/install/wksta/files10.txt
@@ -0,0 +1,94 @@
+[RemoveBackupFiles]
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nethlp.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\net.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\netmsg.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\srvsvc.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\ncpa.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\wfwnet.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\vdmredir.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\ipxroute.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nwlnkmsg.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nwnblink.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\wshnwlnk.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nwlnkcfg.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nwlnksvc.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nwnbexe.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\drivers\srv.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\drivers\nwlink.nwc"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\drivers\nwnblink.nwc"
+ return
+
+[Restore-Oldsys]
+3,srv.nwc , SIZE=0, RENAME=srv.sys
+3,nwlink.nwc , SIZE=0, RENAME=nwlink.sys
+3,nwnblink.nwc, SIZE=0, RENAME=nwnblink.sys
+
+[Restore-Oldexe]
+3,nethlp.nwc , SIZE=0, RENAME=net.hlp
+3,net.nwc , SIZE=0, RENAME=net.exe
+3,netmsg.nwc , SIZE=0, RENAME=netmsg.dll
+3,srvsvc.nwc , SIZE=0, RENAME=srvsvc.dll
+3,ncpa.nwc , SIZE=0, RENAME=ncpa.cpl
+3,wfwnet.nwc , SIZE=0, RENAME=wfwnet.drv
+3,vdmredir.nwc, SIZE=0, RENAME=vdmredir.dll
+
+3,ipxroute.nwc, SIZE=0, RENAME=ipxroute.exe
+3,nwlnkmsg.nwc, SIZE=0, RENAME=nwlnkmsg.dll
+3,nwnblink.nwc, SIZE=0, RENAME=nwnblink.dll
+3,wshnwlnk.nwc, SIZE=0, RENAME=wshnwlnk.dll
+3,nwlnkcfg.nwc, SIZE=0, RENAME=nwlnkcfg.dll
+3,nwlnksvc.nwc, SIZE=0, RENAME=nwlnksvc.exe
+3,nwnbexe.nwc , SIZE=0, RENAME=nwnblink.exe
+
+[Files-Drivers]
+1,nwrdr.sys, SIZE=999
+1,srv.sys, SIZE=999, BACKUP=srv.nwc
+1,nwlink.sys, SIZE=999, BACKUP=nwlink.nwc
+1,nwnblink.sys, SIZE=999, BACKUP=nwnblink.nwc
+
+[Files-nwcfgdll]
+1,nwcfg.dll, SIZE=999
+
+[Files-NWWKSTA]
+2,nwsvc.exe, SIZE=999
+2,nwevent.dll , SIZE=999
+2,nwwks.dll , SIZE=999
+2,nwprovau.dll, SIZE=999
+2,nwapi32.dll, SIZE=999
+2,nw16.exe, SIZE=999
+2,netware.drv, SIZE=999
+2,nwc.cpl, SIZE=999
+2,vwipxspx.dll, SIZE=999
+2,vwipxspx.exe, SIZE=999
+2,nwapi16.dll, SIZE=999
+;
+2,net.hlp, SIZE=999, BACKUP=nethlp.nwc
+2,net.exe, SIZE=999, BACKUP=net.nwc
+2,net1.exe, SIZE=999
+2,netmsg.dll, SIZE=999, BACKUP=netmsg.nwc
+2,srvsvc.dll, SIZE=999, BACKUP=srvsvc.nwc
+2,ncpa.cpl, SIZE=999, BACKUP=ncpa.nwc
+2,wfwnet.drv, SIZE=999, BACKUP=wfwnet.nwc
+2,vdmredir.dll, SIZE=999, BACKUP=vdmredir.nwc
+;
+2,ipxroute.exe, SIZE=999, BACKUP=ipxroute.nwc
+2,nwlnkmsg.dll, SIZE=999, BACKUP=nwlnkmsg.nwc
+2,nwnblink.dll, SIZE=999, BACKUP=nwnblink.nwc
+2,wshnwlnk.dll, SIZE=999, BACKUP=wshnwlnk.nwc
+2,nwlnkcfg.dll, SIZE=999, BACKUP=nwlnkcfg.nwc
+2,nwlnksvc.exe, SIZE=999, BACKUP=nwlnksvc.nwc
+2,nwnblink.exe, SIZE=999, BACKUP=nwnbexe.nwc
+;
+; Performance Monitor
+;
+2,nwperf.ini, SIZE=999
+2,perfnw.dll, SIZE=999
+2,nwperfm.h, SIZE=999
+
+[Files-NTASHelp]
+1,nwdocgw.hlp, SIZE=999, RENAME=nwdoc.hlp
+
+[Files-WINNTHelp]
+1,nwdoc.hlp, SIZE=999
+
+
diff --git a/private/nw/install/wksta/files10a.txt b/private/nw/install/wksta/files10a.txt
new file mode 100644
index 000000000..137bf041d
--- /dev/null
+++ b/private/nw/install/wksta/files10a.txt
@@ -0,0 +1,37 @@
+[RemoveBackupFiles]
+ return
+
+[Restore-Oldexe]
+
+[Restore-Oldsys]
+
+
+[Files-Drivers]
+1,nwrdr.sys, SIZE=999
+
+[Files-nwcfgdll]
+1,nwcfg.dll, SIZE=999
+
+[Files-NWWKSTA]
+1,nwsvc.exe, SIZE=999
+1,nwevent.dll , SIZE=999
+1,nwwks.dll , SIZE=999
+1,nwprovau.dll, SIZE=999
+1,nwapi32.dll, SIZE=999
+1,nw16.exe, SIZE=999
+1,nwc.cpl, SIZE=999
+1,vwipxspx.dll, SIZE=999
+1,vwipxspx.exe, SIZE=999
+1,nwapi16.dll, SIZE=999
+;
+; Performance Monitor
+;
+1,nwperf.ini, SIZE=999
+1,nwperfm.h, SIZE=999
+
+[Files-NTASHelp]
+1,nwdocgw.hlp, SIZE=999, RENAME=nwdoc.hlp
+
+[Files-WINNTHelp]
+1,nwdoc.hlp, SIZE=999
+
diff --git a/private/nw/install/wksta/i386.txt b/private/nw/install/wksta/i386.txt
new file mode 100644
index 000000000..6b9fce89b
--- /dev/null
+++ b/private/nw/install/wksta/i386.txt
@@ -0,0 +1,3 @@
+[ProductType]
+STF_PRODUCT = Winnt
+STF_PLATFORM = I386
diff --git a/private/nw/install/wksta/makefile b/private/nw/install/wksta/makefile
new file mode 100644
index 000000000..14f79b701
--- /dev/null
+++ b/private/nw/install/wksta/makefile
@@ -0,0 +1 @@
+!include $(NTMAKEENV)\makefile.def
diff --git a/private/nw/install/wksta/makefile.inc b/private/nw/install/wksta/makefile.inc
new file mode 100644
index 000000000..37d0d9c77
--- /dev/null
+++ b/private/nw/install/wksta/makefile.inc
@@ -0,0 +1,29 @@
+INFHEADER=$(TARGET_DIRECTORY).txt
+
+!IFNDEF INFLANGUAGE
+INFLANGUAGE=ENG
+!ENDIF
+
+all: oemnsvnw.inf
+
+make_inf: oemnsvnw.inf
+
+clean: cleansrc oemnsvnw.inf
+
+cleansrc:
+ del oemnsvnw.inf
+
+
+!IF "$(QFE_BUILD)" != "1"
+
+oemnsvnw.inf: $(INFHEADER) nw.inf $(INFLANGUAGE).txt files10a.txt
+ copy $(INFHEADER)+$(INFLANGUAGE).txt+nw.inf+files10a.txt oemnsvnw.inf
+ binplace oemnsvnw.inf
+
+!ELSE
+
+oemnsvnw.inf: $(INFHEADER) nw.inf $(INFLANGUAGE).txt files10.txt
+ copy $(INFHEADER)+$(INFLANGUAGE).txt+nw.inf+files10.txt oemnsvnw.inf
+ binplace oemnsvnw.inf
+
+!ENDIF
diff --git a/private/nw/install/wksta/mips.txt b/private/nw/install/wksta/mips.txt
new file mode 100644
index 000000000..8101c7cb2
--- /dev/null
+++ b/private/nw/install/wksta/mips.txt
@@ -0,0 +1,3 @@
+[ProductType]
+STF_PRODUCT = Winnt
+STF_PLATFORM = MIPS
diff --git a/private/nw/install/wksta/nw.inf b/private/nw/install/wksta/nw.inf
new file mode 100644
index 000000000..49491ced5
--- /dev/null
+++ b/private/nw/install/wksta/nw.inf
@@ -0,0 +1,1224 @@
+[Identification]
+ OptionType = NetService
+[LanguagesSupported]
+ ENG
+[Options]
+ NWWKSTA
+[FileConstants]
+UtilityInf = "UTILITY.INF"
+subroutineinf = "SUBROUTN.INF"
+SoftwareType = "service"
+Exit_Code = 0
+NetwareEventDLL = "%SystemRoot%\System32\nwevent.dll"
+Manufacturer = "Microsoft"
+ProductMajorVersion = "3"
+ProductMinorVersion = "1"
+ProductVersion = $(ProductMajorVersion)"."$(ProductMinorVersion)
+ProductNWWKSTAName = "NWCWorkstation"
+ProductNWWKSTAImagePath = "%SystemRoot%\System32\nwsvc.exe"
+NetRuleNWWKSTAType = "nwWsta nwcWorkstation"
+NetRuleNWWKSTAClass = {"nwcWorkstation basic"}
+NetRuleNWWKSTABindable = {"nwcWorkstation nwlinkipxTransport non non 100"}
+NetRuleNWWKSTAUse = $(SoftwareType)" no no"
+NetRuleNWWKSTABindForm = """NwcWorkstation"" yes yes container"
+ProductNWRDRName = "NwRdr"
+ProductNWRDRImagePath = "\SystemRoot\System32\drivers\nwrdr.sys"
+ProductProviderImagePath = "%SystemRoot%\System32\nwprovau.dll"
+ProviderName = $(ProductNWWKSTAName)
+ProductKeyName = $(!NTN_SoftwareBase)"\"$(Manufacturer)"\"$(Product$(Option)Name)"\CurrentVersion"
+ParamKeyName = $(!NTN_ServiceBase)"\"$(Product$(Option)Name)"\Parameters"
+LSAKeyName = "System\CurrentControlSet\Control\LSA"
+[GeneralConstants]
+from = ""
+to = ""
+ExitCodeOk = 0
+ExitCodeCancel = 1
+ExitCodeFatal = 2
+KeyNull = ""
+MAXIMUM_ALLOWED = 33554432
+RegistryErrorIndex = NO_ERROR
+KeyProduct = ""
+KeyParameters = ""
+TRUE = 1
+FALSE = 0
+NoTitle = 0
+ExitState = "Active"
+OldVersionExisted = $(FALSE)
+DriverPath = $(!STF_NTPATH)\drivers
+[date]
+ Now = {} ? $(!LIBHANDLE) GetSystemDate
+
+[DetectDiskSpace]
+ VolumeList = {} ? $(!LIBHANDLE) GetHardDriveLetters
+ VolumeFreeList = {} ? $(!LIBHANDLE) GetHardDriveFreeSpace
+ VolumeFSList = {} ? $(!LIBHANDLE) GetHardDriveFileSystems
+
+[DetectSystemMemory]
+ SystemMemory = "" ? $(!LIBHANDLE) GetMemorySize
+
+[Identify]
+ read-syms Identification
+ set Status = STATUS_SUCCESSFUL
+ set Identifier = $(OptionType)
+ set Media = #("Source Media Descriptions", 1, 1)
+ Return $(Status) $(Identifier) $(Media)
+[ReturnOptions]
+ set Status = STATUS_FAILED
+ set OptionList = {}
+ set OptionTextList = {}
+ set LanguageList = ^(LanguagesSupported, 1)
+ Ifcontains(i) $($0) in $(LanguageList)
+ goto returnoptions
+ else
+ set Status = STATUS_NOLANGUAGE
+ goto finish_ReturnOptions
+ endif
+returnoptions = +
+ set OptionList = ^(Options, 1)
+ ifstr(i) $(!STF_PRODUCT) == "WINNT"
+ set OptionTextList = ^(OptionsWINNTText$($0), 1)
+ else
+ set OptionTextList = ^(OptionsLANMANNTText$($0), 1)
+ endif
+ set Status = STATUS_SUCCESSFUL
+finish_ReturnOptions = +
+ Return $(Status) $(OptionList) $(OptionTextList)
+[InstallOption]
+ set Option = $($1)
+ set SrcDir = $($2)
+ set AddCopy = $($3)
+ set DoCopy = $($4)
+ set DoConfig = $($5)
+ set LanguageList = ^(LanguagesSupported, 1)
+ Ifcontains(i) $($0) NOT-IN $(LanguageList)
+ Return STATUS_NOLANGUAGE
+ endif
+ Debug-Output "OEMNSVNW.INF: STF_CWDDIR is: "$(!STF_CWDDIR)
+ Debug-Output "OEMNSVNW.INF: STF_LANGUAGE is: "$(!STF_LANGUAGE)
+ set-subst LF = "\n"
+ set-subst CR = "\r"
+ ifstr(i) $(!STF_PRODUCT) == "WINNT"
+ read-syms Workstation$(!STF_LANGUAGE)
+ else
+ read-syms Gateway$(!STF_LANGUAGE)
+ endif
+ read-syms GeneralConstants
+ read-syms FileConstants
+ read-syms DialogConstants$(!STF_LANGUAGE)
+ ifstr(i) $(!NTN_Origination) == "NCPA"
+ set Continue = $(OK)
+ endif
+ read-syms FileConstants$(!STF_LANGUAGE)
+ detect date
+ detect DetectSystemMemory
+ detect DetectDiskSpace
+ set-title $(FunctionTitle)
+ set to = Begin
+ set from = Begin
+ set CommonStatus = STATUS_SUCCESSFUL
+ EndWait
+Begin = +
+ Ifstr(i) $(!NTN_InstallMode) == deinstall
+ set OEM_ABANDON_OPTIONS = { $(ProductNWWKSTAName), +
+ $(ProductNWRDRName)}
+ set StartLabel = removeadapter
+ else-Ifstr(i) $(!NTN_InstallMode) == Update
+ set StartLabel = UpgradeSoftware
+ else-Ifstr(i) $(!NTN_InstallMode) == bind
+ set StartLabel = bindingadapter
+ else-Ifstr(i) $(!NTN_InstallMode) == configure
+ Shell $(UtilityInf),RegistryErrorString,CANNOT_CONFIGURE_SOFTWARE
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error: cannot get an error string."
+ goto ShellCodeError
+ endif
+ set Error = $($R0)
+ set from = end
+ set to = end
+ goto nonfatalinfo
+ else
+ set StartLabel = installadapter
+ set OEM_ABANDON_OPTIONS = {}
+ endif
+ set DoWKSTA = FALSE
+ set DoRDR = FALSE
+ set DoNWLINK = FALSE
+ set DoMUP = FALSE
+ Ifstr(i) $(Option) == NWWKSTA
+ set DoWKSTA = TRUE
+ set DoRDR = TRUE
+ set DoNWLINK = TRUE
+ set DoMUP = TRUE
+ Else-ifstr(i) $(Option) == RDR
+ Set DoRDR = TRUE
+ Else
+ Debug-Output "OEMNSVWK.INF: Unrecognized option"
+ Endif
+ set from = $(fatal)
+ set to = $(fatal)
+ goto $(StartLabel)
+installadapter = +
+ GetDriveInPath NtDrive $(!STF_WINDOWSSYSPATH)
+ Shell "" GetFilesSize
+ set RequiredSize = $($R0)
+ ForListDo $(VolumeList)
+ set CurrentVolume = *($(VolumeList), $(#))
+ set CurrentVolumeFree = *($(VolumeFreeList), $(#))
+ Ifstr(i) $(CurrentVolume) == $(NtDrive)
+ set-mul CurrentVolumeFree = $(CurrentVolumeFree) 1024
+ Ifint $(CurrentVolumeFree) < $(RequiredSize)
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(NotEnoughSpace)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto end
+ else
+ goto AfterCheckSpace
+ endif
+ EndIf
+ EndForListDo
+AfterCheckSpace = +
+
+ OpenRegKey $(!REG_H_LOCAL) "" $(!NTN_ServiceBase)"\NWLINKIPX" $(MAXIMUM_ALLOWED) BS_KeyServices
+
+ Ifstr $(BS_KeyServices) == $(KeyNull)
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(InstallNWLINKFirst)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto end
+ endif
+
+ OpenRegKey $(!REG_H_LOCAL) "" $(ProductKeyName) $(MAXIMUM_ALLOWED) KeyProduct
+ Ifstr $(KeyProduct) != $(KeyNull)
+ CloseRegKey $(KeyProduct)
+ Shell $(UtilityInf), VerExistedDlg, $(Product$(Option)Title),+
+ $(ProductVersion)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error: cannot get an error string."
+ goto ShellCodeError
+ endif
+ goto end
+ endif
+ CloseRegKey $(KeyProduct)
+
+ ;
+ ; Make sure Mup exists
+ ;
+ ifstr(i) $(DoMUP) == TRUE
+ ;
+ ; Check whether MUP exists or not.
+ ; If exists, continue.
+ ; Otherwise, popup a dialog and end
+ ;
+ Debug-Output "OEMNSVNW.INF: check MUP registry"
+
+ OpenRegKey $(!REG_H_LOCAL) "" $(!NTN_ServiceBase)"\Mup" $(MAXIMUM_ALLOWED) MupKey
+
+ Ifstr $(MupKey) == $(KeyNull)
+ ;
+ ; Mup does not exist. So, end NWCS setup.
+ ;
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(InstallNTWKSTAFirst)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto end
+ endif
+
+ ;
+ ; It exists. So, continue.
+ ;
+ CloseRegKey $(MupKey)
+ endif
+
+ ;
+ ; Check to make sure that NETWAREWORKSTATION is not there
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" $(!NTN_ServiceBase)"\NetwareWorkstation" $(MAXIMUM_ALLOWED) BS_KeyServices
+
+ Ifstr $(BS_KeyServices) == $(KeyNull)
+ ;
+ ; Good. Let check the "Mark for deletion" service controller problem.
+ ;
+ Shell $(UtilityInf), CreateService, +
+ "NetwareWorkstation", +
+ $(ProductNWWKSTADisplayName), +
+ $(ProductNWWKSTAImagePath), "autoserviceshare", "NetworkProvider", {}, "",+
+ $(NetwareEventDLL)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error"
+ goto ShellCodeError
+ endif
+ debug-output $($R0)
+ set RegistryErrorIndex = $($R0)
+ ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ ;
+ ; it is still there
+ ;
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(RemoveAndReboot)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto end
+ else
+ Shell $(UtilityInf) RemoveService "NetwareWorkstation" "YES"
+ endif
+ else
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(RemoveAndReboot)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ CloseRegKey $(BS_KeyServices)
+ goto end
+ endif
+
+
+ goto nextstep
+nextstep = +
+ StartWait
+ Ifstr(i) $(!NTN_InstallMode) == install
+ Ifint $(OldVersionExisted) == $(FALSE)
+ goto installproduct
+ endif
+ endif
+ goto writeparameters
+installproduct = +
+ CloseRegKey $(ParamKeyName)
+ ifstr(i) $(!NTN_InstallMode) == "install"
+ Ifstr(i) $(DoCopy) == "YES"
+ Shell $(UtilityInf), DoAskSource, $(!STF_CWDDIR), $(SrcDir) YES
+ Ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Goto ShellCodeError
+ Else-Ifstr(i) $($R0) == STATUS_FAILED
+ Shell $(UtilityInf) RegistryErrorString "ASK_SOURCE_FAIL"
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ set Error = $($R0)
+ Goto fatal
+ Else-Ifstr(i) $($R0) == STATUS_USERCANCEL
+ Goto successful
+ Endif
+ Set SrcDir = $($R1)
+ Endif
+ install "Install-nwcfgdll"
+ ifstr(i) $(STF_INSTALL_OUTCOME) != STF_SUCCESS
+ Shell $(UtilityInf) RegistryErrorString "UNABLE_COPY_FILE"
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ set Error = $($R0)
+ goto fatal
+ endif
+ endif
+ set OEM_ABANDON_ON = TRUE
+ LoadLibrary "nw" $(!STF_CWDDIR)\nwcfg.dll !NWCFG_HANDLE
+ Set FLibraryErrCtl = 1
+ ;
+ ; Check the version number
+ ;
+ LibraryProcedure Result $(!NWCFG_HANDLE), GetKernelVersion
+ ifint *($(Result),3) < 528
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(UpgradeFirst)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto end
+ FreeLibrary $(!NWCFG_HANDLE)
+ else-ifint *($(Result),3) > 529
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(NotDaytona)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto end
+ FreeLibrary $(!NWCFG_HANDLE)
+ endif
+
+ ifstr(i) $(!NTN_InstallMode) == "install"
+ install "Install-Option"
+ ifstr(i) $(STF_INSTALL_OUTCOME) != STF_SUCCESS
+ Shell $(UtilityInf) RegistryErrorString "UNABLE_COPY_FILE"
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ set Error = $($R0)
+ goto fatal
+ endif
+ endif
+
+ LibraryProcedure Result $(!NWCFG_HANDLE), SetFileSysChangeValue
+ LibraryProcedure Result $(!NWCFG_HANDLE), AddNetwarePrinterProvidor
+ Set FLibraryErrCtl = 0
+ ;
+ ; Change netware to the top provider
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\Print\Providers" $(MAXIMUM_ALLOWED) PrintProviderKey
+ Ifstr $(PrintProviderKey) != $(KeyNull)
+ GetRegValue $(PrintProviderKey),"Order",OrderInfo
+ set OrderList = *($(OrderInfo),4)
+ set NewOrderList = {$(ProductProviderName)}
+ ForListDo $(OrderList)
+ ifstr(i) $($) != $(ProductProviderName)
+ set NewOrderList = >($(NewOrderList),$($))
+ endif
+ EndForListDo
+ SetRegValue $(PrintProviderKey) {"Order",$(NoTitle),$(!REG_VT_MULTI_SZ),$(NewOrderList)}
+ CloseRegKey $(PrintProviderKey)
+ endif
+
+ ;
+ ; Set Authentication packages
+ ;
+
+ OpenRegKey $(!REG_H_LOCAL) "" $(LSAKeyName) $(MAXIMUM_ALLOWED) LSAKey
+ Ifstr $(LSAKey) != $(KeyNull)
+ GetRegValue $(LSAKey),"Authentication Packages", PackagesInfo
+ set Packages = *($(PackagesInfo), 4)
+ ifcontains(i) "nwprovau" in $(Packages)
+ ; don't do it
+ debug-output "Authentication Packages already exist."
+ else
+ ifstr(i) $(Packages) == ""
+ set Packages = {"nwprovau"}
+ else
+ set Packages = >($(Packages),"nwprovau")
+ endif
+ SetRegValue $(LSAKey) {"Authentication Packages",$(NoTitle),$(!REG_VT_MULTI_SZ),$(Packages)}
+ endif
+ CloseRegKey $(LSAKey)
+ endif
+
+ ifstr(i) $(DoWKSTA) == TRUE
+ Debug-Output "OEMNSVNW.INF: Install Workstation in registry."
+ Set OEM_ABANDON_OPTIONS = >($(OEM_ABANDON_OPTIONS), $(ProductNWWKSTAName))
+ Shell $(UtilityInf), AddSoftwareComponent, $(Manufacturer), +
+ $(ProductNWWKSTAName), +
+ $(ProductNWWKSTAName), +
+ $(ProductNWWKSTADisplayName), $(STF_CONTEXTINFNAME), +
+ $(ProductNWWKSTAImagePath), "autoserviceshare", "NetworkProvider", {}, "",+
+ $(NetwareEventDLL)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error"
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ EndWait
+ Debug-Output "OEMNSVNW.INF: Registry error: add software components"
+ CloseRegKey $($R1)
+ CloseRegKey $($R2)
+ CloseRegKey $($R3)
+ CloseRegKey $($R4)
+ CloseRegKey $($R5)
+ goto fatalregistry
+ endif
+ Set SoftProductKey = $($R1)
+ Set SoftNetRuleKey = $($R2)
+ Set SoftServiceKey = $($R3)
+ Set SoftParameterKey = $($R4)
+ Set SoftLinkageKey = $($R5)
+ set NewValueList = {{SoftwareType,$(NoTitle),$(!REG_VT_SZ),$(SoftwareType)},+
+ {MajorVersion,$(NoTitle),$(!REG_VT_DWORD),$(ProductMajorVersion)},+
+ {MinorVersion,$(NoTitle),$(!REG_VT_DWORD),$(ProductMinorVersion)},+
+ {Title,$(NoTitle),$(!REG_VT_SZ),$(ProductNWWKSTATitle)},+
+ {Description,$(NoTitle),$(!REG_VT_SZ),$(ProductNWWKSTADescription)},+
+ {ServiceName,$(NoTitle),$(!REG_VT_SZ),$(ProductNWWKSTAName)},+
+ {InstallDate,$(NoTitle),$(!REG_VT_DWORD),*($(Now),1)}}
+ Shell $(UtilityInf), AddValueList, $(SoftProductKey), $(NewValueList)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error."
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ EndWait
+ Debug-Output "OEMNSVNW.INF: registry error: add value list."
+ CloseRegKey $(SoftProductKey)
+ CloseRegKey $(SoftNetRuleKey)
+ CloseRegKey $(SoftServiceKey)
+ CloseRegKey $(SoftLinkageKey)
+ CloseRegKey $(SoftParameterKey)
+ goto fatalregistry
+ endif
+ set NewValueList = {{type,$(NoTitle),$(!REG_VT_SZ),$(NetRuleNWWKSTAType)},+
+ {class,$(NoTitle),$(!REG_VT_MULTI_SZ),$(NetRuleNWWKSTAClass)}, +
+ {use,$(NoTitle),$(!REG_VT_SZ),$(NetRuleNWWKSTAUse)}, +
+ {bindform,$(NoTitle),$(!REG_VT_SZ),$(NetRuleNWWKSTABindForm)}, +
+ {bindable,$(NoTitle),$(!REG_VT_MULTI_SZ),$(NetRuleNWWKSTABindable)}, +
+ {InfOption,$(NoTitle),$(!REG_VT_SZ),NWWKSTA}}
+ Shell $(UtilityInf), AddValueList, $(SoftNetRuleKey), $(NewValueList)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error."
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ CloseRegKey $(SoftProductKey)
+ CloseRegKey $(SoftNetRuleKey)
+ CloseRegKey $(SoftServiceKey)
+
+ Shell "" AddParameterKey $(SoftParameterKey)
+ CloseRegKey $(SoftParameterKey)
+
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ CloseRegKey $(SoftLinkageKey)
+ EndWait
+ Debug-Output "OEMNSVNW.INF: Registry error: add value list."
+ goto fatalregistry
+ endif
+ set NewValueList = {{OtherDependencies,$(NoTitle),$(!REG_VT_MULTI_SZ),{"Mup"}}}
+ Shell $(UtilityInf), AddValueList, $(SoftLinkageKey), $(NewValueList)
+ CloseRegKey $(SoftLinkageKey)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error."
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ EndWait
+ Debug-Output "OEMNSVNW.INF: registry error: add value list."
+ goto fatalregistry
+ endif
+
+ ; Remove autoexec.nt statements
+ ;
+ Set FLibraryErrCtl = 1
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "REM Install network redirector"$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\nw16"$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\vwipxspx"$(LF)
+ ;
+ ; Setup string in autoexec.nt
+ ;
+ LibraryProcedure Result $(!NWCFG_HANDLE), AppendSzToFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "REM Install network redirector"$(CR)$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), AppendSzToFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\nw16"$(CR)$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), AppendSzToFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\vwipxspx"$(CR)$(LF)
+ Set FLibraryErrCtl = 0
+ endif
+
+ ifstr(i) $(DoNWLINK) == TRUE
+ ;
+ ; Increase the reference counter
+ ;
+ Shell "utility.inf", IncrementRefCount, "Software\Microsoft\NWLINKIPX\CurrentVersion"
+ endif
+
+ ifstr(i) $(DoRDR) == TRUE
+ Debug-Output "OEMNSVNW.INF: Install Rdr registry"
+ Set OEM_ABANDON_OPTIONS = >($(OEM_ABANDON_OPTIONS), $(ProductNWRDRName))
+ Shell $(UtilityInf), CreateService, $(ProductNWRDRName), +
+ $(ProductNWRDRDisplayName), $(ProductNWRDRImagePath), +
+ "system", "Network", {}, "", +
+ $(NetwareEventDLL)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error"
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ set NWRdrServiceKey = $($R1)
+ CloseRegKey $($R2)
+ CloseRegKey $($R3)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ EndWait
+ Debug-Output "OEMNSVNW.INF: Registry error: add software components"
+ goto fatalregistry
+ endif
+
+ ;
+ ; Add performance monitoring info
+ ;
+ CreateRegKey $(NWRdrServiceKey) {"Performance",$(NoTitle),GenericClass} "" +
+ $(MAXIMUM_ALLOWED) "" KeyPerformance
+
+ set NewValueList = {{Library,$(NoTitle),$(!REG_VT_SZ),"Perfnw.dll"},+
+ {Open,$(NoTitle),$(!REG_VT_SZ),"OpenNetWarePerformanceData"},+
+ {Collect,$(NoTitle),$(!REG_VT_SZ),"CollectNetWarePerformanceData"},+
+ {Close,$(NoTitle),$(!REG_VT_SZ),"CloseNetWarePerformanceData"}}
+
+ Shell $(UtilityInf), AddValueList, $(KeyPerformance), $(NewValueList)
+
+ set RegistryErrorIndex = $($R0)
+
+ CloseRegKey $(KeyPerformance)
+ CloseRegKey $(NWRdrServiceKey)
+
+ ;
+ ; Create performance help information
+ ;
+
+ LibraryProcedure Result $(!NWCFG_HANDLE), GetKernelVersion
+ ifint *($(Result),3) < 529
+ Set FLibraryErrCtl = 1
+ LibraryProcedure STATUS $(!NWCFG_HANDLE), lodctr $(!STF_WINDOWSSYSPATH)\nwperf.ini
+ ; Ignore the error code for now
+ Set FLibraryErrCtl = 0
+ else
+ StartDetachedProcess STATUS "" "" $(!STF_WINDOWSSYSPATH)"\lodctr.exe" "nwperf.ini"
+ ifstr(i) $(STATUS) == "ERROR"
+ debug-output "Cannot detached process"
+ endif
+ endif
+
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ EndWait
+ Debug-Output "OEMNSVNW.INF: Registry error: add performance information"
+ goto fatalregistry
+ endif
+
+ Debug-Output "OEMNSVNW.INF: Add NetworkProvider"
+ Shell $(UtilityInf), AddNetworkProvider, $(ProviderName), +
+ $(ProductProviderImagePath), $(ProductProviderName), "nwrdr"
+ set RegistryErrorIndex = $($R0)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ EndWait
+ Debug-Output "OEMNSVNW.INF: Registry error: add software components"
+ goto fatalregistry
+ endif
+
+ ;
+ ; Put netware provider to the top of the order list
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\NetworkProvider\Order" $(MAXIMUM_ALLOWED) NetProviderKey
+ Ifstr $(NetProviderKey) != $(KeyNull)
+ GetRegValue $(NetProviderKey),"ProviderOrder",OrderInfo
+ set OrderList = *($(OrderInfo),4)
+ Split-String $(OrderList), ",", ProviderList
+ set NewOrderList = $(ProductNWWKSTAName)
+ ForListDo $(ProviderList)
+ ifstr(i) $($) != ","
+ ifstr(i) $($) != $(ProductNWWKSTAName)
+ set NewOrderList = $(NewOrderList)","$($)
+ endif
+ endif
+ EndForListDo
+ SetRegValue $(NetProviderKey) {"ProviderOrder",$(NoTitle),$(!REG_VT_SZ),$(NewOrderList)}
+ CloseRegKey $(NetProviderKey)
+ endif
+
+ Shell "" AddShortName
+
+ OpenRegKey $(!REG_H_LOCAL) "" $(!NTN_ServiceBase)"\"$(ProviderName)"\networkprovider" $(MAXIMUM_ALLOWED) ProviderKey
+ ifstr(i) $(ProviderKey) != ""
+ set NewValueList = {{Class,$(NoTitle),$(!REG_VT_DWORD),3}}
+ Shell $(UtilityInf) AddValueList $(ProviderKey) $(NewValueList)
+ endif
+ CloseRegKey $(ProviderKey)
+
+ LibraryProcedure Status1, $(!LIBHANDLE), CheckFileExistance, $(!STF_WINDOWSSYSPATH)"\novell.cpl"
+ ifstr(i) $(Status1) == "YES"
+ LibraryProcedure Status2, $(!LIBHANDLE), RenFile, $(!STF_WINDOWSSYSPATH)"\novell.cpl", $(!STF_WINDOWSSYSPATH)"\novell.bak"
+ endif
+
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\WOW" $(MAXIMUM_ALLOWED) WowKey
+ ifstr(i) $(WowKey) != ""
+ GetRegValue $(WowKey),"KnownDLLS", KnownDLLsInfo
+ Split-String *($(KnownDLLsInfo),4), " ", KnownDLLsList
+ Ifcontains(i) "netware.drv" not-in $(KnownDLLsList)
+ ifstr(i) *($(KnownDLLsInfo),4) == ""
+ set KnownDLLs = "netware.drv"
+ else
+ set KnownDLLs = *($(KnownDLLsInfo),4)" netware.drv"
+ endif
+ SetRegValue $(WowKey) {"KnownDLLS",$(NoTitle),$(!REG_VT_SZ),$(KnownDLLs)}
+ endif
+ CloseRegKey $(WowKey)
+ endif
+
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Services\LanmanServer\Parameters" $(MAXIMUM_ALLOWED) ServerParmKey
+ ifstr(i) $(ServerParmKey) != ""
+ SetRegValue $(ServerParmKey) {"EnableSharedNetDrives",$(NoTitle),$(!REG_VT_DWORD),1}
+ CloseRegKey $(ServerParmKey)
+ endif
+ endif
+writeparameters = +
+
+ FreeLibrary $(!NWCFG_HANDLE)
+
+ EndWait
+ goto successful
+ConfigureBrowser = +
+ goto successful
+bindingadapter =+
+ set Error = "Binding: Sorry, not yet implemented."
+ goto fatal
+removeadapter = +
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\WOW" $(MAXIMUM_ALLOWED) WowKey
+ ifstr(i) $(WowKey) != ""
+ GetRegValue $(WowKey),"KnownDLLS", KnownDLLsInfo
+ Split-String *($(KnownDLLsInfo),4), " ", KnownDLLsList
+ set KnownDLLs = ""
+ Ifcontains(i) "netware.drv" in $(KnownDLLsList)
+ ForListDo $(KnownDLLsList)
+ ifstr(i) $($) != " "
+ ifstr(i) $($) != "netware.drv"
+ ifstr(i) $(KnownDLLs) == ""
+ set KnownDLLs = $($)
+ else
+ set KnownDLLs = $(KnownDLLs)" "$($)
+ endif
+ endif
+ endif
+ EndForListDo
+ else
+ set KnownDLLs = *($(KnownDLLsInfo),4)
+ endif
+ SetRegValue $(WowKey) {"KnownDLLS",$(NoTitle),$(!REG_VT_SZ),$(KnownDLLs)}
+ CloseRegKey $(WowKey)
+ endif
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Services\LanmanServer\Parameters" $(MAXIMUM_ALLOWED) ServerParmKey
+ ifstr(i) $(ServerParmKey) != ""
+ SetRegValue $(ServerParmKey) {"EnableSharedNetDrives",$(NoTitle),$(!REG_VT_DWORD),0}
+ CloseRegKey $(ServerParmKey)
+ endif
+
+ LoadLibrary "nw" $(!STF_CWDDIR)\nwcfg.dll !NWCFG_HANDLE
+ Set FLibraryErrCtl = 1
+ LibraryProcedure Result $(!NWCFG_HANDLE), DeleteNetwarePrinterProvidor
+ LibraryProcedure Result $(!NWCFG_HANDLE), DeleteGatewayPassword
+ Set FLibraryErrCtl = 0
+
+ LibraryProcedure Result $(!NWCFG_HANDLE), GetKernelVersion
+ ifint *($(Result),3) < 529
+ Set FLibraryErrCtl = 1
+ LibraryProcedure STATUS $(!NWCFG_HANDLE), unlodctr nwrdr
+ ; Ignore the error code for now
+ Set FLibraryErrCtl = 0
+ else
+ StartDetachedProcess STATUS "" "" $(!STF_WINDOWSSYSPATH)"\unlodctr.exe" "nwrdr"
+ ifstr(i) $(STATUS) == "ERROR"
+ debug-output "Cannot detached process"
+ endif
+ endif
+
+ ;
+ ; remove Authentication Packages
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" $(LSAKeyName) $(MAXIMUM_ALLOWED) LSAKey
+ Ifstr $(LSAKey) != $(KeyNull)
+ GetRegValue $(LSAKey),"Authentication Packages", PackagesInfo
+ set Packages = *($(PackagesInfo), 4)
+ ifcontains(i) "nwprovau" not-in $(Packages)
+ ; don't do it
+ ; something wrong....
+ debug-output "Authentication Packages does not exist.."
+ else
+ set NewPackages = {}
+ ForListDo $(Packages)
+ ifstr(i) $($) != "nwprovau"
+ ifstr(i) $(NewPackages) == {}
+ set NewPackages = {$($)}
+ else
+ set NewPackages = >($(NewPackages),$($))
+ endif
+ endif
+ EndForListDo
+ SetRegValue $(LSAKey) {"Authentication Packages",$(NoTitle),$(!REG_VT_MULTI_SZ),$(NewPackages)}
+ endif
+ CloseRegKey $(LSAKey)
+ endif
+
+ ifcontains(i) $(ProductNWWKSTAName) in $(OEM_ABANDON_OPTIONS)
+ Shell $(UtilityInf), RemoveSoftwareComponent, $(Manufacturer), +
+ $(ProductNWWKSTAName)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error"
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ goto fatalregistry
+ endif
+ endif
+ ForListDo {$(ProductNWRDRName)}
+ ifcontains(i) $($) in $(OEM_ABANDON_OPTIONS)
+ Shell $(UtilityInf), RemoveService, $($), "YES"
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error"
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ goto fatalregistry
+ endif
+ endif
+ EndForListDo
+ Shell "UTILITY.INF", DecrementRefCount, "Software\Microsoft\NWLINKIPX\CurrentVersion"
+ ;
+ ; Remove autoexec.nt statements
+ ;
+ Set FLibraryErrCtl = 1
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "REM Install network redirector"$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\nw16"$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\vwipxspx"$(LF)
+ Set FLibraryErrCtl = 0
+
+ Shell $(UtilityInf) RemoveNetworkProvider $(ProviderName)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ Debug-Output "OEMNSVNW.INF: ShellCode error"
+ goto ShellCodeError
+ endif
+ set RegistryErrorIndex = $($R0)
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ goto fatalregistry
+ endif
+
+ ;
+ ; Remove ShrotName
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\NetworkProvider\ShortName" $(MAXIMUM_ALLOWED) ShortNameKey
+ ifstr $(ShortNameKey) != $(KeyNull)
+ DeleteRegValue $(ShortNameKey) "NW"
+ else
+ ;
+ ; we must be able to open the provider key
+ ;
+ debug-output "something wrong..."
+ endif
+
+ FreeLibrary $(!NWCFG_HANDLE)
+
+ Install "RestoreFiles"
+
+ Set FLibraryErrCtl = 1
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nwc.bak"
+ LibraryProcedure Status1, $(!LIBHANDLE), DelFile, $(!STF_WINDOWSSYSPATH)"\nwapi32.bak"
+ LibraryProcedure Status1, $(!LIBHANDLE), RenFile, $(!STF_WINDOWSSYSPATH)"\nwc.cpl" $(!STF_WINDOWSSYSPATH)"\nwc.bak"
+ LibraryProcedure Status1, $(!LIBHANDLE), RenFile, $(!STF_WINDOWSSYSPATH)"\nwapi32.dll" $(!STF_WINDOWSSYSPATH)"\nwapi32.bak"
+ Set FLibraryErrCtl = 0
+
+ Shell "" RemoveBackupFiles
+
+ goto end
+UpgradeSoftware = +
+ LoadLibrary "nw" $(!STF_CWDDIR)\nwcfg.dll !NWCFG_HANDLE
+ LibraryProcedure Result $(!NWCFG_HANDLE), GetKernelVersion
+ ifint *($(Result),3) > 528
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "NONFATAL", $(NotDaytona)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto end
+ endif
+ FreeLibrary $(!NWCFG_HANDLE)
+
+
+ OpenRegKey $(!REG_H_LOCAL) "" $(ProductKeyName)"\NetRules" $(MAXIMUM_ALLOWED) KeyNetRules
+ Ifstr $(KeyNetRules) != $(KeyNull)
+ GetRegValue $(KeyNetRules),"InfName", InfNameInfo
+ set !UG_Filename = *($(InfNameInfo), 4)
+ CloseRegKey $(KeyNetRules)
+ else
+ Split-String $(!NTN_Infname), "\", FilenameList
+ QueryListSize ListSize $(FilenameList)
+ set !UG_Filename = *($(FilenameList), $(ListSize))
+ endif
+
+ Install "Install-Update"
+ ifstr(i) $(STF_INSTALL_OUTCOME) != STF_SUCCESS
+ goto fatal
+ endif
+
+ set AddCopy = "YES"
+ set DoCopy = "YES"
+ install "Install-nwcfgdll"
+ ifstr(i) $(STF_INSTALL_OUTCOME) != STF_SUCCESS
+ goto fatal
+ endif
+
+ LoadLibrary "nw" $(!STF_CWDDIR)\nwcfg.dll !NWCFG_HANDLE
+
+ OpenRegKey $(!REG_H_LOCAL) "" $(ProductKeyName) $(MAXIMUM_ALLOWED) KeyProduct
+
+ Ifstr $(KeyProduct) != $(KeyNull)
+ CloseRegKey $(KeyProduct)
+
+ ;
+ ; Check whether we are update beta 1 or beta 2.
+ ; Beta 2 will have a Performance key under \nwcworkstation\parameters
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" $(!NTN_ServiceBase)"\Nwrdr\Performance" $(MAXIMUM_ALLOWED) KeyPerformance
+
+ Ifstr $(KeyPerformance) != $(KeyNull)
+ ;
+ ; We are upgrading beta 2. Do nothing
+ ;
+ CloseRegKey $(KeyPerformance)
+
+ Set FLibraryErrCtl = 1
+ LibraryProcedure Result $(!NWCFG_HANDLE), DeleteGatewayPassword
+ Set FLibraryErrCtl = 0
+
+ LibraryProcedure Result $(!NWCFG_HANDLE), GetKernelVersion
+ ifint *($(Result),3) < 529
+ Set FLibraryErrCtl = 1
+ LibraryProcedure STATUS $(!NWCFG_HANDLE), unlodctr nwrdr
+ LibraryProcedure STATUS $(!NWCFG_HANDLE), lodctr $(!STF_WINDOWSSYSPATH)\nwperf.ini
+ Set FLibraryErrCtl = 0
+ endif
+
+ else
+ ;
+ ; We are upgrading beta 1. Do the followings:
+ ; 1. Add SetFileSysChangeValue call out.
+ ; 2. Add "vwipxspx" to autoexec.nt
+ ; 3. Add Performance stuff
+ ; 4. Add lodctr
+ ; 5. Change the provider device name
+ ; 6. rename novell.cpl
+ ; 7. Add WOW's known DLL
+ ; 8. Add EnableShareNetDrivers
+ ; 9. Change name
+ ; 10. Change class type
+ ;
+
+ ;
+ ; Do 1. Add SetFileSysChangeValue
+ ;
+ LibraryProcedure Result $(!NWCFG_HANDLE), SetFileSysChangeValue
+
+ ; Do 2. Remove autoexec.nt statements
+ ;
+ Set FLibraryErrCtl = 1
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "REM Install network redirector"$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\nw16"$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), RemoveSzFromFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\vwipxspx"$(LF)
+ ;
+ ; Setup string in autoexec.nt
+ ;
+ LibraryProcedure Result $(!NWCFG_HANDLE), AppendSzToFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "REM Install network redirector"$(CR)$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), AppendSzToFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\nw16"$(CR)$(LF)
+ LibraryProcedure Result $(!NWCFG_HANDLE), AppendSzToFile, $(!STF_WINDOWSSYSPATH)"\autoexec.nt", "lh %SystemRoot%\system32\vwipxspx"$(CR)$(LF)
+ Set FLibraryErrCtl = 0
+
+ ;
+ ; Do 3. Add performance stuff
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" $(!NTN_ServiceBase)"\nwrdr" $(MAXIMUM_ALLOWED) KeyNwrdr
+ CreateRegKey $(KeyNwrdr) {"Performance",$(NoTitle),GenericClass} "" +
+ $(MAXIMUM_ALLOWED) "" KeyPerformance
+
+ set NewValueList = {{Library,$(NoTitle),$(!REG_VT_SZ),"Perfnw.dll"},+
+ {Open,$(NoTitle),$(!REG_VT_SZ),"OpenNetWarePerformanceData"},+
+ {Collect,$(NoTitle),$(!REG_VT_SZ),"CollectNetWarePerformanceData"},+
+ {Close,$(NoTitle),$(!REG_VT_SZ),"CloseNetWarePerformanceData"}}
+
+ Shell $(UtilityInf), AddValueList, $(KeyPerformance), $(NewValueList)
+
+ set RegistryErrorIndex = $($R0)
+
+ CloseRegKey $(KeyPerformance)
+ CloseRegKey $(KeyNwrdr)
+
+ ;
+ ; Do 4. Add lodctr
+ ;
+
+ LibraryProcedure Result $(!NWCFG_HANDLE), GetKernelVersion
+ ifint *($(Result),3) < 529
+ Set FLibraryErrCtl = 1
+ LibraryProcedure STATUS $(!NWCFG_HANDLE), lodctr $(!STF_WINDOWSSYSPATH)\nwperf.ini
+ ; Ignore the error code for now
+ Set FLibraryErrCtl = 0
+ endif
+
+ Ifstr(i) $(RegistryErrorIndex) != NO_ERROR
+ EndWait
+ Debug-Output "OEMNSVNW.INF: Registry error: add performance information"
+ goto fatalregistry
+ endif
+
+ ;
+ ; Do 6. rename novell.cpl
+ ;
+ LibraryProcedure Status1, $(!LIBHANDLE), CheckFileExistance, $(!STF_WINDOWSSYSPATH)"\novell.cpl"
+ ifstr(i) $(Status1) == "YES"
+ LibraryProcedure Status2, $(!LIBHANDLE), RenFile, $(!STF_WINDOWSSYSPATH)"\novell.cpl", $(!STF_WINDOWSSYSPATH)"\novell.bak"
+ endif
+
+ ;
+ ; Do 7. Add WOW's known DLL
+ ;
+
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\WOW" $(MAXIMUM_ALLOWED) WowKey
+ ifstr(i) $(WowKey) != ""
+ GetRegValue $(WowKey),"KnownDLLS", KnownDLLsInfo
+ Split-String *($(KnownDLLsInfo),4), " ", KnownDLLsList
+ Ifcontains(i) "netware.drv" not-in $(KnownDLLsList)
+ ifstr(i) *($(KnownDLLsInfo),4) == ""
+ set KnownDLLs = "netware.drv"
+ else
+ set KnownDLLs = *($(KnownDLLsInfo),4)" netware.drv"
+ endif
+ SetRegValue $(WowKey) {"KnownDLLS",$(NoTitle),$(!REG_VT_SZ),$(KnownDLLs)}
+ endif
+ CloseRegKey $(WowKey)
+ endif
+ endif
+ endif
+
+ ;
+ ; Do 5. Change the provider device name
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Services\NWCWorkstation\networkprovider" $(MAXIMUM_ALLOWED) ProviderKey
+ ifstr(i) $(ProviderKey) != ""
+ SetRegValue $(ProviderKey) {Devicename,$(NoTitle),$(!REG_VT_SZ),"\device\nwrdr"}
+ SetRegValue $(ProviderKey) {Name,$(NoTitle),$(!REG_VT_SZ),$(ProductProviderName)}
+ CloseRegKey $(ProviderKey)
+ endif
+
+ ;
+ ; Do 8. Add EnableShareNetDrivers
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Services\LanmanServer\Parameters" $(MAXIMUM_ALLOWED) ServerParmKey
+ ifstr(i) $(ServerParmKey) != ""
+ SetRegValue $(ServerParmKey) {"EnableSharedNetDrives",$(NoTitle),$(!REG_VT_DWORD),1}
+ CloseRegKey $(ServerParmKey)
+ endif
+
+ ;
+ ; do 9. Change name
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "Software\Microsoft\NWCWorkstation\CurrentVersion" $(MAXIMUM_ALLOWED) CurrentVersionKey
+ ifstr(i) $(CurrentVersionKey) != ""
+ SetRegValue $(CurrentVersionKey) {"Description",$(NoTitle),$(!REG_VT_SZ),$(NWType)}
+ SetRegValue $(CurrentVersionKey) {"Title",$(NoTitle),$(!REG_VT_SZ),$(NWType)}
+ CloseRegKey $(CurrentVersionKey)
+ endif
+
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Services\NWCWorkstation" $(MAXIMUM_ALLOWED) nwcKey
+ ifstr(i) $(nwcKey) != ""
+ SetRegValue $(nwcKey) {"DisplayName",$(NoTitle),$(!REG_VT_SZ),$(NWType)}
+ CloseRegKey $(nwcKey)
+ endif
+
+ Set FLibraryErrCtl = 1
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\Print\Providers" $(MAXIMUM_ALLOWED) PrintProviderKey
+ ifstr(i) $(PrintProviderKey) != ""
+ GetRegValue $(PrintProviderKey) "Order" OrderInfo
+ ifcontains(i) $(OldPrintProviderName) in *($(OrderInfo),4)
+ ; spool is not started
+
+ DeleteRegKey $(PrintProviderKey) $(OldPrintProviderName)
+ OpenRegKey $(PrintProviderKey) "" $(ProductProviderName) $(MAXIMUM_ALLOWED) ProductProviderKey
+ ifstr $(ProductProviderKey) == $(KeyNull)
+ CreateRegKey $(PrintProviderKey) {$(ProductProviderName),$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" ProductProviderKey
+ endif
+ ifstr $(ProductProviderKey) != $(KeyNull)
+ SetRegValue $(ProductProviderKey) {"Name",$(NoTitle),$(!REG_VT_SZ),"nwprovau.dll"}
+ endif
+
+ ;
+ ; Change it to top provider
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\Print\Providers" $(MAXIMUM_ALLOWED) PrintProviderKey
+ Ifstr $(PrintProviderKey) != $(KeyNull)
+ GetRegValue $(PrintProviderKey),"Order",OrderInfo
+ set OrderList = *($(OrderInfo),4)
+ set NewOrderList = {$(ProductProviderName)}
+ ForListDo $(OrderList)
+ ifstr(i) $($) != $(OldPrintProviderName)
+ ifstr(i) $($) != $(ProductProviderName)
+ set NewOrderList = >($(NewOrderList),$($))
+ endif
+ endif
+ EndForListDo
+ SetRegValue $(PrintProviderKey) {"Order",$(NoTitle),$(!REG_VT_MULTI_SZ),$(NewOrderList)}
+ CloseRegKey $(PrintProviderKey)
+ endif
+ endif
+ endif
+ Set FLibraryErrCtl = 0
+
+ Shell "" AddShortName
+
+ FreeLibrary $(!NWCFG_HANDLE)
+
+ goto end
+successful = +
+ goto end
+warning = +
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "WARNING", $(Error)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ ifstr(i) $($R1) == "OK"
+ goto $(to)
+ else-ifstr(i) $($R1) == "CANCEL"
+ goto $(from)
+ else
+ goto end
+ endif
+nonfatalinfo = +
+ Set CommonStatus = STATUS_USERCANCEL
+ Set Severity = STATUS
+ goto nonfatalmsg
+nonfatal = +
+ Set Severity = NONFATAL
+ goto nonfatalmsg
+nonfatalmsg = +
+ ifstr(i) $(Error) == ""
+ Set Severity = NONFATAL
+ Shell $(UtilityInf) RegistryErrorString "SETUP_FAIL"
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ set Error = $($R0)
+ endif
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), $(Severity), $(Error)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ ifstr(i) $($R1) == "OK"
+ goto $(from)
+ else
+ goto "end"
+ endif
+fatalregistry = +
+ Shell $(UtilityInf) RegistryErrorString $(RegistryErrorIndex)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ set Error = $($R0)
+ goto fatal
+fatal = +
+ ifstr(i) $(Error) == ""
+ Shell $(UtilityInf) RegistryErrorString "SETUP_FAIL"
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ set Error = $($R0)
+ endif
+ Shell $(subroutineinf) SetupMessage, $(!STF_LANGUAGE), "FATAL", $(Error)
+ ifint $($ShellCode) != $(!SHELL_CODE_OK)
+ goto ShellCodeError
+ endif
+ goto setfailed
+ShellCodeError = +
+ set DlgType = "MessageBox"
+ set STF_MB_TITLE = "Error: "$(FunctionTitle)
+ set STF_MB_TEXT = $(ShellCodeErrorText)
+ set STF_MB_TYPE = 1
+ set STF_MB_ICON = 3
+ set STF_MB_DEF = 1
+ ui start "Error Message"
+ goto setfailed
+setfailed = +
+ set CommonStatus = STATUS_FAILED
+ ifstr(i) $(OEM_ABANDON_ON) == TRUE
+ set OEM_ABANDON_ON = FALSE
+ goto removeadapter
+ endif
+ goto end
+end = +
+ goto term
+term = +
+ Return $(CommonStatus)
+[RestoreFiles]
+ AddSectionFilesToCopyList Restore-Oldexe $(!STF_WINDOWSSYSPATH) $(!STF_WINDOWSSYSPATH)
+ AddSectionFilesToCopyList Restore-Oldsys $(!STF_WINDOWSSYSPATH)\drivers $(!STF_WINDOWSSYSPATH)\drivers
+ set !STF_NCPA_FLUSH_COPYLIST = TRUE
+ CopyFilesInCopyList
+ Exit
+[Install-nwcfgdll]
+ set STF_VITAL = ""
+ ifstr(i) $(AddCopy) == "YES"
+ AddSectionFilesToCopyList Files-nwcfgdll $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ endif
+ ifstr(i) $(DoCopy) == "YES"
+ set !STF_NCPA_FLUSH_COPYLIST = TRUE
+ CopyFilesInCopyList
+ endif
+ Exit
+[Install-Option]
+ set STF_VITAL = ""
+ ifstr(i) $(AddCopy) == "YES"
+ AddSectionFilesToCopyList Files-$(Option) $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ AddSectionFilesToCopyList Files-Drivers $(SrcDir) $(!STF_WINDOWSSYSPATH)\drivers
+ ifstr(i) $(!STF_PRODUCT) == "WINNT"
+ AddSectionFilesToCopyList Files-WINNTHelp $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ else
+ AddSectionFilesToCopyList Files-NTASHelp $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ endif
+ endif
+ ifstr(i) $(DoCopy) == "YES"
+ set !STF_NCPA_FLUSH_COPYLIST = TRUE
+ CopyFilesInCopyList
+ endif
+ ifstr(i) $(DoConfig) == "YES"
+ endif
+ Exit
+[Install-Update]
+ set STF_VITAL = ""
+ AddSectionFilesToCopyList Files-$(Option) $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ AddSectionFilesToCopyList Files-Drivers $(SrcDir) $(!STF_WINDOWSSYSPATH)\drivers
+ AddSectionFilesToCopyList Files-Inf $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ ifstr(i) $(!STF_PRODUCT) == "WINNT"
+ AddSectionFilesToCopyList Files-WINNTHelp $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ else
+ AddSectionFilesToCopyList Files-NTASHelp $(SrcDir) $(!STF_WINDOWSSYSPATH)
+ endif
+ set !STF_NCPA_FLUSH_COPYLIST = TRUE
+ CopyFilesInCopyList
+ Exit
+
+[AddShortName]
+ read-syms GeneralConstants
+ read-syms FileConstants
+ read-syms FileConstants$(!STF_LANGUAGE)
+ ;
+ ; Create Short name
+ ;
+ OpenRegKey $(!REG_H_LOCAL) "" "System\CurrentControlSet\Control\NetworkProvider" $(MAXIMUM_ALLOWED) NetProviderKey
+ ifstr $(NetProviderKey) != $(KeyNull)
+ OpenRegKey $(NetProviderKey) "" "ShortName" $(MAXIMUM_ALLOWED) ShortNameKey
+ ifstr $(ShortNameKey) == $(KeyNull)
+ ;
+ ; Create short key if we cannot open it
+ ;
+ CreateRegKey $(NetProviderKey) {"ShortName",$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" ShortNameKey
+ endif
+ ifstr $(ShortNameKey) != $(KeyNull)
+ SetRegValue $(ShortNameKey) {"NW",$(NoTitle),$(!REG_VT_SZ),$(ProductProviderName)}
+ endif
+ else
+ ;
+ ; we must be able to open the provider key
+ ;
+ debug-output "something wrong..."
+ endif
+
+ return
+
+[AddParameterKey]
+ read-syms GeneralConstants
+ set SoftParameterKey = $($0)
+ CreateRegKey $(SoftParameterKey) {"Logon",$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" LogonKey
+ CreateRegKey $(SoftParameterKey) {"Option",$(NoTitle),GenericClass} "" $(MAXIMUM_ALLOWED) "" OptionKey
+
+ Set FLibraryErrCtl = 1
+ ;
+ ; 2 is the equal to SetValue
+ ;
+ LibraryProcedure Result $(!NWCFG_HANDLE), SetEverybodyPermission, $(OptionKey), 2
+ Set FLibraryErrCtl = 0
+
+ CloseRegKey $(LogonKey)
+ CloseRegKey $(OptionKey)
+
+ Return
+
+[GetFilesSize]
+ set FileSizeList = >(^(Files-Drivers,3),^(Files-NWWKSTA,3))
+ set TotalSize = 0
+ ForListDo $(FileSizeList)
+ ForListDo $($)
+ Debug-Output $($)
+ Split-String $($) "=" SplitString
+ set Size = *($(SplitString),3)
+ set-add TotalSize = $(TotalSize) $(Size)
+ EndForListDo
+ EndForListDo
+ set-div SizeInK = $(TotalSize) 1024
+ return $(SizeInK)
+
+[Files-Inf]
+1, oemsetup.inf, SIZE=1000, RENAME=$(!UG_Filename)
diff --git a/private/nw/install/wksta/nwperf.ini b/private/nw/install/wksta/nwperf.ini
new file mode 100644
index 000000000..09ad2d364
--- /dev/null
+++ b/private/nw/install/wksta/nwperf.ini
@@ -0,0 +1,37 @@
+[info]
+drivername=NWrdr
+symbolfile=nwperfm.h
+
+[languages]
+009=English
+
+[text]
+NWOBJ_009_NAME=Client Service for NetWare
+NWOBJ_009_HELP=Client Service for NetWare object type.
+
+PACKET_BURST_READ_ID_009_NAME=Packet Burst Read NCP Count/sec
+PACKET_BURST_READ_ID_009_HELP=Packet Burst Read NCP Count/sec is the rate of Netware Core Protocol requests for Packet Burst Read. Packet Burst is a windowing protocol that improves performance.
+
+PACKET_BURST_READ_TO_ID_009_NAME=Packet Burst Read Timeouts/sec
+PACKET_BURST_READ_TO_ID_009_HELP=Packet Burst Read Timeouts/sec is the rate the Netware(R) Workstation Compatible Service needs to retransmit a Burst Read Request because the Netware server took too long to respond.
+
+PACKET_BURST_WRITE_ID_009_NAME=Packet Burst Write NCP Count/sec
+PACKET_BURST_WRITE_ID_009_HELP=Packet Burst Write NCP Count/sec is the rate of Netware Core Protocol requests for Packet Burst Write. Packet Burst is a windowing protocol that improves performance.
+
+PACKET_BURST_WRITE_TO_ID_009_NAME=Packet Burst Write Timeouts/sec
+PACKET_BURST_WRITE_TO_ID_009_HELP=Packet Burst Write Timeouts/sec is the rate the Netware(R) Workstation Compatible Service need to retransmit a Burst Write Request because the Netware server took too long to respond.
+
+PACKET_BURST_IO_ID_009_NAME=Packet Burst IO/sec
+PACKET_BURST_IO_ID_009_HELP=Packet Burst IO/sec is the sum of Packet Burst Read NCPs/sec and Packet Burst Write NCPs/sec.
+
+CONNECT_2X_ID_009_NAME=Connect NetWare 2.x
+CONNECT_2X_ID_009_HELP=Connect NetWare 2.x counts connections to NetWare 2.x servers.
+
+CONNECT_3X_ID_009_NAME=Connect NetWare 3.x
+CONNECT_3X_ID_009_HELP=Connect NetWare 3.x counts connections to NetWare 3.x servers.
+
+CONNECT_4X_ID_009_NAME=Connect NetWare 4.x
+CONNECT_4X_ID_009_HELP=Connect NetWare 4.x counts connections to NetWare 4.x servers.
+
+
+
diff --git a/private/nw/install/wksta/nwperfm.h b/private/nw/install/wksta/nwperfm.h
new file mode 100644
index 000000000..f4934e675
--- /dev/null
+++ b/private/nw/install/wksta/nwperfm.h
@@ -0,0 +1,24 @@
+//
+// NWPerfM.h
+//
+// Offset definition file for exensible counter objects and counters
+//
+// These "relative" offsets must start at 0 and be multiples of 2 (i.e.
+// even numbers). In the Open Procedure, they will be added to the
+// "First Counter" and "First Help" values of the device they belong to,
+// in order to determine the absolute location of the counter and
+// object names and corresponding help text in the registry.
+//
+// this file is used by the extensible counter DLL code as well as the
+// counter name and help text definition file (.INI) file that is used
+// by LODCTR to load the names into the registry.
+//
+#define NWOBJ 0
+#define PACKET_BURST_READ_ID 2
+#define PACKET_BURST_READ_TO_ID 4
+#define PACKET_BURST_WRITE_ID 6
+#define PACKET_BURST_WRITE_TO_ID 8
+#define PACKET_BURST_IO_ID 10
+#define CONNECT_2X_ID 12
+#define CONNECT_3X_ID 14
+#define CONNECT_4X_ID 16
diff --git a/private/nw/install/wksta/ppc.txt b/private/nw/install/wksta/ppc.txt
new file mode 100644
index 000000000..4c0794041
--- /dev/null
+++ b/private/nw/install/wksta/ppc.txt
@@ -0,0 +1,4 @@
+[ProductType]
+STF_PRODUCT = Winnt
+STF_PLATFORM = PPC
+ \ No newline at end of file
diff --git a/private/nw/install/wksta/sources b/private/nw/install/wksta/sources
new file mode 100644
index 000000000..5f820ad93
--- /dev/null
+++ b/private/nw/install/wksta/sources
@@ -0,0 +1,42 @@
+!IF 0
+
+Copyright (c) 1989 Microsoft Corporation
+
+Module Name:
+
+ sources.
+
+Abstract:
+
+ This file specifies the target component being built and the list of
+ sources files needed to build that component. Also specifies optional
+ compiler switches and libraries that are unique for the component being
+ built.
+
+
+Author:
+
+ Steve Wood (stevewo) 12-Apr-1989
+
+
+Revision History:
+
+ Terence Kwan (terryk) 13-Aug-1992
+ add make_inf
+
+!ENDIF
+
+MAJORCOMP=inf
+MINORCOMP=inf
+
+INCLUDES=.
+
+TARGETNAME=inf
+TARGETPATH=obj
+TARGETEXT = cpl
+TARGETTYPE= macro
+
+
+SOURCES=
+
+NTTARGETFILES=make_inf