diff options
Diffstat (limited to '')
-rw-r--r-- | private/nw/install/setupdll/common.h | 122 | ||||
-rw-r--r-- | private/nw/install/setupdll/dllinit.c | 65 | ||||
-rw-r--r-- | private/nw/install/setupdll/lodctr.c | 1531 | ||||
-rw-r--r-- | private/nw/install/setupdll/makefile | 10 | ||||
-rw-r--r-- | private/nw/install/setupdll/nwcfg.cxx | 318 | ||||
-rw-r--r-- | private/nw/install/setupdll/nwcfg.def | 19 | ||||
-rw-r--r-- | private/nw/install/setupdll/nwcfg.h | 22 | ||||
-rw-r--r-- | private/nw/install/setupdll/nwcfg.hxx | 28 | ||||
-rw-r--r-- | private/nw/install/setupdll/nwcfg.prf | 1 | ||||
-rw-r--r-- | private/nw/install/setupdll/nwcfg.rc | 20 | ||||
-rw-r--r-- | private/nw/install/setupdll/removesz.c | 58 | ||||
-rw-r--r-- | private/nw/install/setupdll/rules.mk | 4 | ||||
-rw-r--r-- | private/nw/install/setupdll/setvalue.c | 696 | ||||
-rw-r--r-- | private/nw/install/setupdll/sources | 48 | ||||
-rw-r--r-- | private/nw/install/setupdll/unlodctr.c | 1006 |
15 files changed, 3948 insertions, 0 deletions
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); + +} |