//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation, 1997. // // File: N W C L I I N F . C P P // // Contents: NetWare client configuration notify object. // Functionality from old INF // // Notes: // // Author: jeffspr 24 Jun 1997 // //---------------------------------------------------------------------------- #include "pch.h" #pragma hdrstop #include "lmerr.h" #include "lmcons.h" #include "lmserver.h" #include "ncreg.h" #include "nwclidef.h" #include "nwcliobj.h" extern const WCHAR c_szRegKeyCtlLsa[]; //---[ Constants ]------------------------------------------------------------ const WCHAR c_szConfigDLLName[] = NW_CONFIG_DLL_NAME; const WCHAR c_szAuthPackageName[] = NW_AUTH_PACKAGE_NAME; const WCHAR c_szParamOptionKeyPath[] = NW_NWC_PARAM_OPTION_KEY; const WCHAR c_szParamLogonKeyPath[] = NW_NWC_PARAM_LOGON_KEY; const WCHAR c_szNwDocGWHelpName[] = L"nwdocgw.hlp"; const WCHAR c_szNwDocGWCNTName[] = L"nwdocgw.cnt"; const WCHAR c_szNwDocHelpName[] = L"nwdoc.hlp"; const WCHAR c_szNwDocCNTName[] = L"nwdoc.cnt"; const DWORD c_dwOptionKeyPermissions = KEY_SET_VALUE | KEY_CREATE_SUB_KEY; //---[ Prototypes ]----------------------------------------------------------- // See the function headers for descriptions // HRESULT HrAppendNetwareToAuthPackages(); HRESULT HrCreateParametersSubkeys(); HRESULT HrMungeAutoexecNT(); BOOL FMoveSzToEndOfFile( PSTR pszAutoexecName, PSTR pszMatch); HRESULT HrAddNetWareToWOWKnownList(); HRESULT HrUpdateLanmanSharedDrivesValue(); HRESULT HrRemoveNetwareFromAuthPackages(); HRESULT HrRemoveNetWareFromWOWKnownList(); HRESULT HrDeleteParametersSubkeys(); HRESULT HrRenameNWDocFiles(); //+--------------------------------------------------------------------------- // // Member: CNWClient::HrLoadConfigDLL // // Purpose: Load nwcfg.dll, so we can call some of the functions within. // Also, do the GetProcAddress calls for all of the functions // that we might need. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT CNWClient::HrLoadConfigDLL() { HRESULT hr = S_OK; AssertSz(!m_hlibConfig, "This should not be getting initialized twice"); TraceTag(ttidNWClientCfgFn, ">> CNWClient::HrLoadConfigDLL"); m_hlibConfig = LoadLibrary(c_szConfigDLLName); if (!m_hlibConfig) { DWORD dwLastError = GetLastError(); TraceLastWin32Error("HrLoadConfigDLL() failed"); // More specific info // TraceTag(ttidNWClientCfg, "HrLoadConfigDLL() - LoadLibrary failed on %S, Err: %d", c_szConfigDLLName, dwLastError); hr = E_FAIL; goto Exit; } // $$REVIEW: We probably won't need all of these, so make sure that we've // cut out the ones that we're no longer using (or have never used). // m_pfnAppendSzToFile = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "AppendSzToFile"); m_pfnRemoveSzFromFile = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "RemoveSzFromFile"); m_pfnGetKernelVersion = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "GetKernelVersion"); m_pfnSetEverybodyPermission = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "SetEverybodyPermission"); m_pfnlodctr = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "lodctr"); m_pfnunlodctr = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "unlodctr"); m_pfnDeleteGatewayPassword = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "DeleteGatewayPassword"); m_pfnSetFileSysChangeValue = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "SetFileSysChangeValue"); m_pfnCleanupRegistryForNWCS = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "CleanupRegistryForNWCS"); m_pfnSetupRegistryForNWCS = (NWCFG_PROC) GetProcAddress(m_hlibConfig, "SetupRegistryForNWCS"); if (!m_pfnAppendSzToFile || !m_pfnRemoveSzFromFile || !m_pfnGetKernelVersion || !m_pfnSetEverybodyPermission || !m_pfnlodctr || !m_pfnunlodctr || !m_pfnDeleteGatewayPassword || !m_pfnSetFileSysChangeValue || !m_pfnCleanupRegistryForNWCS || !m_pfnSetupRegistryForNWCS) { TraceLastWin32Error("HrLoadConfigDLL() - GetProcAddress failed"); hr = E_FAIL; goto Exit; } Exit: TraceTag(ttidNWClientCfgFn, "<< CNWClient::HrLoadConfigDLL"); TraceError("HrLoadConfigDLL", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: CNWClient::FreeConfigDLL // // Purpose: Free nwcfg.dll, and NULL out the function pointers. // // Arguments: // (none) // // Returns: No return (VOID) // // Author: jeffspr 24 Jun 1997 // // Notes: // VOID CNWClient::FreeConfigDLL() { TraceTag(ttidNWClientCfgFn, ">> CNWClient::FreeConfigDLL()"); // If we successfully loaded the library, free it. if (m_hlibConfig) { // Free up the library resources. FreeLibrary(m_hlibConfig); m_hlibConfig = NULL; m_pfnAppendSzToFile = NULL; m_pfnRemoveSzFromFile = NULL; m_pfnGetKernelVersion = NULL; m_pfnSetEverybodyPermission = NULL; m_pfnlodctr = NULL; m_pfnunlodctr = NULL; m_pfnDeleteGatewayPassword = NULL; m_pfnSetFileSysChangeValue = NULL; m_pfnCleanupRegistryForNWCS = NULL; m_pfnSetupRegistryForNWCS = NULL; } TraceTag(ttidNWClientCfgFn, "<< CNWClient::FreeConfigDLL()"); } //+--------------------------------------------------------------------------- // // Member: CNWClient::HrInstallCodeFromOldINF // // Purpose: This contains all of the logic from the old oemnsvnw.inf, or // at least calls to helper functions that perform all of the // logic. This runs pretty much straight through the old // installadapter code. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT CNWClient::HrInstallCodeFromOldINF() { HRESULT hr = S_OK; BOOL fResult = FALSE; // Get result from NWCFG functions. We won't use it though. PWSTR pszDummy = NULL; TraceTag(ttidNWClientCfgFn, ">> CNWClient::HrInstallCodeFromOldINF()"); hr = HrLoadConfigDLL(); if (FAILED(hr)) { // Error traced in the call itself. goto Exit; } // Call the NWCFG function that does (their comment): // "set the FileSysChangeValue to please NETWARE.DRV. // also set win.ini parameter so wfwnet.drv knows we are there." fResult = m_pfnSetupRegistryForNWCS(0, NULL, &pszDummy); if (!fResult) { TraceTag(ttidNWClientCfg, "HrInstallCodeFromOldINF() - m_pfnSetupRegistryForNWCS failed"); goto Exit; } // Append our name to the Lsa Authentication packages reg value. hr = HrAppendNetwareToAuthPackages(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } // Create the required subkeys under the services\NWCWorkstation\parameters // key // hr = HrCreateParametersSubkeys(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } // Munge the autoexec.nt (or autoexec.tmp) file. Pass the function pointers // to the munge that will allow it to manipulate the autoexec.nt hr = HrMungeAutoexecNT(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } hr = HrAddNetWareToWOWKnownList(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } // If this is the gateway that we're installing, do the work that will // allow us to share a redirected resource. // if (PF_SERVER == m_pf) { hr = HrUpdateLanmanSharedDrivesValue(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } // On the server build, rename nwdocgw.* to nwdoc.* hr = HrRenameNWDocFiles(); if (FAILED(hr)) { goto Exit; } } Exit: // This will work even if the handle is NULL. FreeConfigDLL(); TraceTag(ttidNWClientCfgFn, "<< CNWClient::HrInstallCodeFromOldINF()"); TraceError("CNWClient::HrInstallCodeFromOldINF()", hr); return hr; } //+--------------------------------------------------------------------------- // // Member: CNWClient::HrRemoveCodeFromOldINF // // Purpose: This contains all of the remove logic from the old // oemnsvnw.inf, or at least calls to helper functions that // perform all of the logic. This runs pretty much straight // through the old removeadapter code. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT CNWClient::HrRemoveCodeFromOldINF() { HRESULT hr = S_OK; BOOL fResult = FALSE; // Get result from NWCFG functions. We won't use it though. PWSTR pszDummy = NULL; TraceTag(ttidNWClientCfgFn, ">> CNWClient::HrRemoveCodeFromOldINF()"); hr = HrLoadConfigDLL(); if (FAILED(hr)) { // Error traced in the call itself. goto Exit; } // Call the NWCFG function that does (their comment): // "set the FileSysChangeValue to please NETWARE.DRV. // also set win.ini parameter so wfwnet.drv knows we are there." fResult = m_pfnCleanupRegistryForNWCS(0, NULL, &pszDummy); if (!fResult) { TraceTag(ttidNWClientCfg, "HrRemoveCodeFromOldINF() - m_pfnCleanupRegistryForNWCS failed"); goto Exit; } // Remove our name from the Lsa Authentication packages reg value. hr = HrRemoveNetwareFromAuthPackages(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } // Delete the NWC subkeys under the services\NWCWorkstation\parameters // key // hr = HrDeleteParametersSubkeys(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } hr = HrRemoveNetWareFromWOWKnownList(); if (FAILED(hr)) { // Error traced within the function itself. // goto Exit; } Exit: // This will work even if the handle is NULL. FreeConfigDLL(); TraceTag(ttidNWClientCfgFn, "<< CNWClient::HrRemoveCodeFromOldINF()"); TraceError("CNWClient::HrRemoveCodeFromOldINF()", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrAppendNetwareToAuthPackages // // Purpose: Helper function for HrCodeFromOldINF() - Appends the netware // authentication provider name to the end of the LSA // authentication packages value. // // Arguments: // (none) // // Returns: S_OK or valid Win32 Error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrAppendNetwareToAuthPackages() { HRESULT hr = S_OK; TraceTag(ttidNWClientCfgFn, ">> HrAppendNetwareToAuthPackages"); // Call the cool new AddString... function // hr = HrRegAddStringToMultiSz( (PWSTR) c_szAuthPackageName, HKEY_LOCAL_MACHINE, c_szRegKeyCtlLsa, L"Authentication Packages", STRING_FLAG_ENSURE_AT_END, 0); if (FAILED(hr)) { TraceTag(ttidNWClientCfg, "HrAppendNetwareToAuthPackages() - Failed to " "Add string to multi-sz 'Authentication Packages' in key: %S", c_szRegKeyCtlLsa); goto Exit; } Exit: TraceTag(ttidNWClientCfgFn, "<< HrAppendNetwareToAuthPackages"); TraceError("HrAppendNetwareToAuthPackages", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrRemoveNetwareFromAuthPackages // // Purpose: Helper function for HrCodeFromOldINF() - Appends the netware // authentication provider name to the end of the LSA // authentication packages value. // // Arguments: // (none) // // Returns: S_OK or valid Win32 Error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrRemoveNetwareFromAuthPackages() { HRESULT hr = S_OK; TraceTag(ttidNWClientCfgFn, ">> HrRemoveNetwareFromAuthPackages"); // Call the cool new AddString... function // hr = HrRegRemoveStringFromMultiSz( (PWSTR) c_szAuthPackageName, HKEY_LOCAL_MACHINE, c_szRegKeyCtlLsa, L"Authentication Packages", STRING_FLAG_REMOVE_ALL); if (FAILED(hr)) { TraceTag(ttidNWClientCfg, "HrRemoveNetwareFromAuthPackages() - Failed to " "Remove string to multi-sz 'Authentication Packages' in key: %S", c_szRegKeyCtlLsa); goto Exit; } Exit: TraceTag(ttidNWClientCfgFn, "<< HrRemoveNetwareFromAuthPackages"); TraceError("HrRemoveNetwareFromAuthPackages", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrNwLibSetEverybodyPermission // // Purpose: Set the registry key to everybody "Set Value" (or whatever // the caller want.) // // Arguments: // hKey [] The handle of the registry key to set security on // dwPermission [] The permission to add to "everybody" // // Returns: // // Author: jeffspr 18 Jun 1997 // // Notes: // HRESULT HrNwLibSetEverybodyPermission( IN HKEY hKey, IN DWORD dwPermission) { LONG err; // error code PSECURITY_DESCRIPTOR psd = NULL; // related SD PSID pSid = NULL; // original SID PACL pDacl = NULL; // Absolute DACL PACL pSacl = NULL; // Absolute SACL PSID pOSid = NULL; // Absolute Owner SID PSID pPSid = NULL; // Absolute Primary SID do { // Not a loop, just for breaking out of error // // Initialize all the variables... // // world sid authority SID_IDENTIFIER_AUTHORITY SidAuth= SECURITY_WORLD_SID_AUTHORITY; DWORD cbSize=0; // Security key size PACL pAcl; // original ACL BOOL fDaclPresent; BOOL fDaclDefault; SECURITY_DESCRIPTOR absSD; // Absolute SD DWORD AbsSize = sizeof(SECURITY_DESCRIPTOR); // Absolute SD size DWORD DaclSize; // Absolute DACL size DWORD SaclSize; // Absolute SACL size DWORD OSidSize; // Absolute OSID size DWORD PSidSize; // Absolute PSID size // Get the original DACL list RegGetKeySecurity( hKey, DACL_SECURITY_INFORMATION, NULL, &cbSize); psd = (PSECURITY_DESCRIPTOR *)LocalAlloc(LMEM_ZEROINIT, cbSize+sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID)); pDacl = (PACL)LocalAlloc(LMEM_ZEROINIT, cbSize+sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID)); pSacl = (PACL)LocalAlloc(LMEM_ZEROINIT, cbSize); pOSid = (PSID)LocalAlloc(LMEM_ZEROINIT, cbSize); pPSid = (PSID)LocalAlloc(LMEM_ZEROINIT, cbSize); DaclSize = cbSize+sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID); SaclSize = cbSize; OSidSize = cbSize; PSidSize = cbSize; if (( NULL == psd) || ( NULL == pDacl) || ( NULL == pSacl) || ( NULL == pOSid) || ( NULL == pPSid)) { err = ERROR_INSUFFICIENT_BUFFER; break; } if ( (err = RegGetKeySecurity( hKey, DACL_SECURITY_INFORMATION, psd, &cbSize )) != ERROR_SUCCESS ) { break; } if ( !GetSecurityDescriptorDacl( psd, &fDaclPresent, &pAcl, &fDaclDefault )) { err = GetLastError(); break; } // Increase the size for an extra ACE pAcl->AclSize += sizeof(ACCESS_ALLOWED_ACE)+sizeof(ACCESS_MASK)+sizeof(SID); // Get World SID if ( (err = RtlAllocateAndInitializeSid( &SidAuth, 1, SECURITY_WORLD_RID, 0, 0, 0, 0, 0, 0, 0, &pSid)) != ERROR_SUCCESS) { break; } // Add Permission ACE if ( !AddAccessAllowedAce(pAcl, ACL_REVISION, dwPermission ,pSid)) { err = GetLastError(); break; } // Convert from relate format to absolute format if ( !MakeAbsoluteSD( psd, &absSD, &AbsSize, pDacl, &DaclSize, pSacl, &SaclSize, pOSid, &OSidSize, pPSid, &PSidSize )) { err = GetLastError(); break; } // Set SD if ( !SetSecurityDescriptorDacl( &absSD, TRUE, pAcl, FALSE )) { err = GetLastError(); break; } if ( (err = RegSetKeySecurity( hKey, DACL_SECURITY_INFORMATION, psd )) != ERROR_SUCCESS ) { break; } } while (FALSE); // Clean up the memory RtlFreeSid( pSid ); LocalFree( psd ); LocalFree( pDacl ); LocalFree( pSacl ); LocalFree( pOSid ); LocalFree( pPSid ); return (HRESULT_FROM_WIN32(err)); } //+--------------------------------------------------------------------------- // // Function: HrSetEverybodyPermissionsOnOptionsKeys // // Purpose: Recurse through the options keys (if any), and set the // "Everybody" permissions on them. // // Arguments: // hkeyOptions [] // dwPermissions [] // // Returns: // // Author: jeffspr 10 Sep 1997 // // Notes: // HRESULT HrSetEverybodyPermissionsOnOptionsKeys(HKEY hkeyOptions, DWORD dwPermissions) { HRESULT hr = S_OK; DWORD dwIndex = 0; WCHAR szSubkeyName[MAX_PATH+1]; FILETIME ft; Assert(hkeyOptions); // First, do it on the root key. // hr = HrNwLibSetEverybodyPermission(hkeyOptions, dwPermissions); // Enumerate the keys, and set it on them as well // while (SUCCEEDED(hr)) { DWORD dwSubkeyNameSize = MAX_PATH+1; // Get the next key (starting with 0) // hr = HrRegEnumKeyEx( hkeyOptions, dwIndex++, szSubkeyName, &dwSubkeyNameSize, NULL, NULL, &ft); if (SUCCEEDED(hr)) { HKEY hkeyUser = NULL; // Open that key for write hr = HrRegOpenKeyEx(hkeyOptions, szSubkeyName, KEY_ALL_ACCESS, &hkeyUser); if (SUCCEEDED(hr)) { hr = HrNwLibSetEverybodyPermission(hkeyUser, dwPermissions); } RegSafeCloseKey(hkeyUser); } } if (hr == HRESULT_FROM_WIN32(ERROR_NO_MORE_ITEMS)) { hr = S_OK; } TraceError("HrSetEverybodyPermissionsOnOptionsKeys", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrCreateParametersSubkeys // // Purpose: Creates the subkeys under the NWCWorkstation parameters key. // This could have been done in the INF, but there were some // permissions that needed to be set on the keys as well, so // all of the work now takes place in this function. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrCreateParametersSubkeys() { HRESULT hr = S_OK; HKEY hkeyOption = NULL; HKEY hkeyLogon = NULL; DWORD dwDisposition = 0; TraceTag(ttidNWClientCfgFn, ">> HrCreateParametersSubkeys"); hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szParamOptionKeyPath, 0, KEY_ALL_ACCESS, NULL, &hkeyOption, &dwDisposition); if (FAILED(hr)) { TraceTag(ttidNWClientCfg, "HrCreateParametersSubkeys() - failed to " "create/open key %S", c_szParamOptionKeyPath); goto Exit; } hr = HrRegCreateKeyEx(HKEY_LOCAL_MACHINE, c_szParamLogonKeyPath, 0, KEY_SET_VALUE, NULL, &hkeyLogon, &dwDisposition); if (FAILED(hr)) { TraceTag(ttidNWClientCfg, "HrCreateParametersSubkeys() - failed to " "create/open key %S", c_szParamLogonKeyPath); goto Exit; } hr = HrSetEverybodyPermissionsOnOptionsKeys(hkeyOption, c_dwOptionKeyPermissions); if (FAILED(hr)) { TraceTag(ttidNWClientCfg, "HrSetEverybodyPermissionsOnOptionsKeys failed, hr: 0x%08x", hr); goto Exit; } Exit: // Close the hkeys, if they're open RegSafeCloseKey(hkeyLogon); RegSafeCloseKey(hkeyOption); TraceTag(ttidNWClientCfgFn, ">> HrCreateParametersSubkeys"); TraceError("HrCreateParametersSubkeys", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrDeleteParametersSubkeys // // Purpose: Deletes the subkeys under the NWCWorkstation parameters key. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrDeleteParametersSubkeys() { HRESULT hr = S_OK; TraceTag(ttidNWClientCfgFn, ">> HrDeleteParametersSubkeys"); // Note: We need to be taking ownership of these keys so we can delete // them. Regardless, ignore if the key deletions fail. hr = HrRegDeleteKeyTree(HKEY_LOCAL_MACHINE, c_szParamOptionKeyPath); if (FAILED(hr)) { TraceTag(ttidNWClientCfg, "HrDeleteParametersSubkeys() - failed to " "delete key %S, hr = 0x%08x", c_szParamOptionKeyPath, hr); hr = S_OK; } hr = HrRegDeleteKey(HKEY_LOCAL_MACHINE, c_szParamLogonKeyPath); if (FAILED(hr)) { TraceTag(ttidNWClientCfg, "HrDeleteParametersSubkeys() - failed to " "delete key %S, hr = 0x%08x", c_szParamLogonKeyPath, hr); hr = S_OK; } TraceTag(ttidNWClientCfgFn, ">> HrDeleteParametersSubkeys"); TraceError("HrDeleteParametersSubkeys", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: FCheckForExistingFile // // Purpose: Checks for the existance of the passed in file. Should be // common-ized. // // Arguments: // pszFileToCheck [] The file name to verify // // Returns: TRUE if the file was found, FALSE otherwise. // // Author: jeffspr 24 Jun 1997 // // Notes: $$TODO: Should be improved if we move this to common code. // The thing that it doesn't do is distinguish between a file // being "not found" and a file error (such as access rights // or sharing violations) on the CreateFile call. // BOOL FCheckForExistingFile( PSTR pszFileToCheck ) { BOOL fReturn = TRUE; HANDLE hFile = NULL; TraceTag(ttidNWClientCfgFn, ">> FCheckForExistingFile"); hFile = CreateFileA(pszFileToCheck, GENERIC_READ, 0, // No sharing allowed NULL, // No security attributes OPEN_EXISTING, // Fail if file doesn't exist FILE_ATTRIBUTE_NORMAL, NULL); if (hFile != INVALID_HANDLE_VALUE) { CloseHandle(hFile); hFile = NULL; } else { // This was previously a bug. We weren't setting FALSE here, which made // the function somewhat useless. fReturn = FALSE; } TraceTag(ttidNWClientCfgFn, "<< FCheckForExistingFile"); return fReturn; } //+--------------------------------------------------------------------------- // // Function: KillTrailingWhitespace // // Purpose: Remove whitespace from a non-UNICODE string. This is a utility // function for the autoexec.nt parser // // Arguments: // pszKillMyWhitespace [] String from which to remove whitespace // // Returns: // // Author: jeffspr 24 Jun 1997 // // Notes: // VOID KillTrailingWhitespace( PSTR pszKillMyWhitespace ) { long lLength = 0; if (!pszKillMyWhitespace) { Assert(pszKillMyWhitespace); goto Exit; } lLength = lstrlenA(pszKillMyWhitespace); if (lLength == 0) { goto Exit; } while (isspace(pszKillMyWhitespace[lLength-1])) { pszKillMyWhitespace[--lLength] = '\0'; } Exit: return; } //+--------------------------------------------------------------------------- // // Function: FMoveSzToEndOfFile // // Purpose: Find a string in the file of this name, and if it's present, // move the string to the end of the file. This is used by the // autoexec.nt parser to move the IPX stuff to the end of the // file. This is a rewrite of similar code in the nwcfg.dll // stuff. That code apparently wasn't UNICODE, and didn't work // for what we were doing. // // Arguments: // pszAutoexecName [] Name of the file to modify // pszMatch [] String to move // // Returns: // // Author: jeffspr 24 Jun 1997 // // Notes: // BOOL FMoveSzToEndOfFile( PSTR pszAutoexecName, PSTR pszMatch ) { FILE * hsrcfile = NULL; FILE * hdesfile = NULL; char * pszTempname = NULL; char szInput[1000]; TraceTag(ttidNWClientCfgFn, ">> FMoveSzToEndOfFile"); // Get a temp name // pszTempname = tmpnam(NULL); // Open the original and the destination files // hsrcfile = fopen(pszAutoexecName, "r"); hdesfile = fopen(pszTempname, "w"); if (( hsrcfile != NULL ) && ( hdesfile != NULL )) { while (fgets(szInput,1000,hsrcfile)) { CHAR szInputCopy[1000]; // Copy to another temp buffer so that when we remove the // trailing whitespace for the comparison, we won't lose the // original text. // strcpy(szInputCopy, szInput); // Remove the trailing whitespace, so we only have to compare the // real text // KillTrailingWhitespace(szInputCopy); // Compare the strings // if (lstrcmpiA(szInputCopy, pszMatch) != 0) { // If the strings weren't identical, then we still want // to copy the line // fputs(szInput,hdesfile); } } // Append the string to the end of the file. fputs(pszMatch, hdesfile); fputs("\r\n",hdesfile); } if (hsrcfile != NULL) { fclose(hsrcfile); } if (hdesfile != NULL) { fclose(hdesfile); } if (( hsrcfile != NULL ) && ( hdesfile != NULL )) { CopyFileA(pszTempname,pszAutoexecName, FALSE); DeleteFileA(pszTempname); } TraceTag(ttidNWClientCfgFn, "<< FMoveSzToEndOfFile"); return TRUE; } //+--------------------------------------------------------------------------- // // Function: HrMungeAutoexecNT // // Purpose: Move the IPX stuff to the end of the autoexec.nt. Do this by // calling FMoveSzToEndOfFile on each of our lines. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrMungeAutoexecNT() { HRESULT hr = S_OK; CHAR szAutoNTPath[MAX_PATH+1] = {0}; CHAR szAutoTmpPath[MAX_PATH+1] = {0}; CHAR szWindowsDirANSI[MAX_PATH+1] = {0}; PSTR pszAutoPath = NULL; BOOL fResult = FALSE; PCWSTR pszRem1 = NULL; PSTR pszaRem1MultiByte = NULL; int iLength = 0; TraceTag(ttidNWClientCfgFn, ">> HrMungeAutoexecNT"); // Get the windows directory if (GetSystemWindowsDirectoryA(szWindowsDirANSI, sizeof(szWindowsDirANSI)) == 0) { TraceLastWin32Error("HrMungeAutoexecNT - Call to GetWindowsDirectoryA"); hr = HrFromLastWin32Error(); goto Exit; } // Build the path to the autoexec.nt // wsprintfA(szAutoNTPath, "%s\\system32\\%s", szWindowsDirANSI, "autoexec.nt"); if (FCheckForExistingFile(szAutoNTPath) == FALSE) { wsprintfA(szAutoTmpPath, "%s\\system32\\%s", szWindowsDirANSI, "autoexec.tmp"); if (FCheckForExistingFile(szAutoTmpPath) == FALSE) { // Per the old INF, skip the whole shebang. goto Exit; } else { pszAutoPath = szAutoTmpPath; } } else { pszAutoPath = szAutoNTPath; } // At this point, we should have found at least one valid // autoexec.nt or .tmp file. If not, we should have dropped out of the // function Assert(pszAutoPath); pszRem1 = SzLoadStringPcch(_Module.GetResourceInstance(), IDS_AUTOEXEC_REM1, &iLength); if (!pszRem1 || iLength == 0) { AssertSz(FALSE, "Failed to load STR_AUTOEXEC_REM from the resources"); TraceTag(ttidNWClientCfg, "ERROR: Failed to load STR_AUTOEXEC_REM from the resources"); hr = E_FAIL; goto Exit; } // Allocate memory for the demoted string. pszaRem1MultiByte = (PSTR) MemAlloc(lstrlenW(pszRem1) + 1); if (!pszaRem1MultiByte) { TraceTag(ttidNWClientCfg, "ERROR: Failed to alloc memory for demoted string"); hr = E_OUTOFMEMORY; goto Exit; } // Demote the loaded string to multibyte (single char) WideCharToMultiByte( CP_ACP, // ANSI code page 0, // flags for non-mapped character action pszRem1, // source string -1, // source string is NULL terminated pszaRem1MultiByte, // destination string (multibyte) lstrlenW(pszRem1) + 1, // size of destination string NULL, // default char on non-mapped char NULL); // return for default char mapping action // Move the REM from the autoexec.nt // fResult = FMoveSzToEndOfFile(pszAutoPath, pszaRem1MultiByte); if (!fResult) { // Traced in called function. hr = E_FAIL; goto Exit; } // Move the line that loads nw16 // fResult = FMoveSzToEndOfFile(pszAutoPath, "lh %SystemRoot%\\system32\\nw16"); if (!fResult) { // Traced in called function. hr = E_FAIL; goto Exit; } // Move the line that loads vwipxspx // fResult = FMoveSzToEndOfFile(pszAutoPath, "lh %SystemRoot%\\system32\\vwipxspx"); if (!fResult) { // Traced in called function. hr = E_FAIL; goto Exit; } Exit: MemFree(pszaRem1MultiByte); TraceTag(ttidNWClientCfgFn, "<< HrMungeAutoexecNT"); TraceError("HrMungeAutoexecNT", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrAddNetWareToWOWKnownList // // Purpose: Add the netware.drv to the WOW "known DLLS" list. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrAddNetWareToWOWKnownList() { HRESULT hr = S_OK; TraceTag(ttidNWClientCfgFn, ">> HrAddNetWareToWOWKnownList"); // Call the cool new AddString... function // hr = HrRegAddStringToSz( L"netware.drv", HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\WOW", L"KnownDLLS", L' ', STRING_FLAG_ENSURE_AT_END, 0); TraceTag(ttidNWClientCfgFn, "<< HrAddNetWareToWOWKnownList"); TraceError("HrAddNetWareToWOWKnownList", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrRemoveNetWareFromWOWKnownList // // Purpose: Add the netware.drv to the WOW "known DLLS" list. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrRemoveNetWareFromWOWKnownList() { HRESULT hr = S_OK; TraceTag(ttidNWClientCfgFn, ">> HrRemoveNetWareFromWOWKnownList"); // Call the cool new AddString... function // hr = HrRegRemoveStringFromSz( L"netware.drv", HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Control\\WOW", L"KnownDLLS", L' ', STRING_FLAG_REMOVE_SINGLE); TraceTag(ttidNWClientCfgFn, "<< HrRemoveNetWareFromWOWKnownList"); TraceError("HrRemoveNetWareFromWOWKnownList", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrUpdateLanmanSharedDrivesValue // // Purpose: If the LanmanServer service exists, make sure that they have the // EnableSharedNetDrives value turned on. // // Arguments: // (none) // // Returns: S_OK or valid Win32 error code. // // Author: jeffspr 24 Jun 1997 // // Notes: // HRESULT HrUpdateLanmanSharedDrivesValue() { HRESULT hr = S_OK; const DWORD c_dwESNDValue = 1; HKEY hkeyLMSP = NULL; SERVER_INFO_1540 si1540 = {0}; NET_API_STATUS nas = ERROR_SUCCESS; DWORD dwDisposition = 0; TraceTag(ttidNWClientCfgFn, ">> HrUpdateLanmanSharedDrivesValue"); // Open the LanmanServer parameters key, if it exists. If it doesn't exist, // it will still return S_OK, but the hkey will still be NULL. // hr = HrRegCreateKeyEx( HKEY_LOCAL_MACHINE, L"System\\CurrentControlSet\\Services\\LanmanServer\\Parameters", REG_OPTION_NON_VOLATILE, KEY_SET_VALUE, // samDesired NULL, &hkeyLMSP, &dwDisposition); if (FAILED(hr)) { TraceTag(ttidNWClientCfgFn, "Failed to create/open the " "LanmanServer\\Parameters key"); goto Exit; } Assert(hkeyLMSP); hr = HrRegSetDword( hkeyLMSP, L"EnableSharedNetDrives", c_dwESNDValue); if (FAILED(hr)) { TraceTag(ttidNWClientCfgFn, "Failed to set the EnabledSharedNetDrives value in " "HrUpdateLanmanSharedDrivesValue()"); goto Exit; } // Call the NetServerSetInfo with the Enable Shared Net Drives info (1540). // This will allow this info to be set dynamically (so as not to require a // restart of the "Server" service. // si1540.sv1540_enablesharednetdrives = TRUE; // Set the server info for the EnableSharedDrives value. This will cause it to // take effect if the service is running (and will do nothing if it is not). // nas = NetServerSetInfo(NULL, 1540, (LPBYTE) &si1540, NULL); if (nas != NERR_Success) { // It's actually OK if this fails in one condition (0x842), because // it WILL fail if the server service That's not a problem, because // the value that I set in the registry above will be picked up the // next time the server service starts. // // OK, cheesy, but I don't know the define, I just know that this is the // right return code for our ignorable failure. // if (nas != 0x842) { AssertSz(nas == 0x842, "NetServerSetInfo failed for a reason other " "than the service not running (which would have been ok)"); } } Exit: // Close the hkey, if it's open RegSafeCloseKey(hkeyLMSP); TraceTag(ttidNWClientCfgFn, "<< HrUpdateLanmanSharedDrivesValue"); TraceError("HrUpdateLanmanSharedDrivesValue()", hr); return hr; } //+--------------------------------------------------------------------------- // // Function: HrRenameNWDocFiles // // Purpose: On the server install, rename the nwdocgw.* files, since // whether we're on CSNW or GSNW, the files are always called // nwdoc.* // // Arguments: // (none) // // Returns: // // Author: jeffspr 13 Jul 1997 // // Notes: // HRESULT HrRenameNWDocFiles() { HRESULT hr = S_OK; WCHAR szWindowsDir[MAX_PATH+1]; WCHAR szSourceName[MAX_PATH+1]; WCHAR szTargetName[MAX_PATH+1]; // Get the windows directory if (GetSystemWindowsDirectory(szWindowsDir, MAX_PATH) == 0) { TraceLastWin32Error("HrRenameNWDocFiles - Call to GetSystemWindowsDirectory"); hr = HrFromLastWin32Error(); goto Exit; } // Build the path for the first rename // wsprintfW(szSourceName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocGWHelpName); wsprintfW(szTargetName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocHelpName); // Rename the .HLP file. If this fails, no big deal. // if (!MoveFileEx(szSourceName, szTargetName, MOVEFILE_REPLACE_EXISTING)) { // For debugging only. // DWORD dwLastError = GetLastError(); } // Build the path for the second rename // wsprintfW(szSourceName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocGWCNTName); wsprintfW(szTargetName, L"%s\\system32\\%s", szWindowsDir, c_szNwDocCNTName); // Rename the .CNT file. If this fails, no big deal. // if (!MoveFileEx(szSourceName, szTargetName, MOVEFILE_REPLACE_EXISTING)) { // For debugging only. // DWORD dwLastError = GetLastError(); } Exit: return hr; }