Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

616 lines
16 KiB

//+------------------------------------------------------------------
//
// Project: Windows NT4 DS Client Setup Wizard
//
// Purpose: Installs the Windows NT4 DS Client Files
//
// File: doinst.cpp
//
// History: Aug. 1998 Zeyong Xu Created
// Jan 2000 Jeff Jones (JeffJon) Modified
// - changed to be an NT setup
//
//------------------------------------------------------------------
#include <windows.h>
#include <setupapi.h>
#include <advpub.h>
#include "resource.h"
#include "dscsetup.h"
#include "wizard.h"
#include "doinst.h"
extern SInstallVariables g_sInstVar;
// do installation
DWORD DoInstallation(HWND hWnd)
{
if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS)
{
// set the fake progressbar for DCOM and WAB nstall
g_sInstVar.m_uTimerID = SetTimer(hWnd,
1,
1000, // 1 seconds
Timer1Proc);
// do the custom action of NTLMv2
if(!DoEncSChannel())
g_sInstVar.m_nSetupResult = SETUP_ERROR;
// stop the fake progressbar
if(g_sInstVar.m_uTimerID)
KillTimer(hWnd, g_sInstVar.m_uTimerID);
// install adsi
if (!LaunchProcess(STR_INSTALL_ADSI))
{
g_sInstVar.m_nSetupResult = SETUP_ERROR;
}
// install dsclient
if(g_sInstVar.m_nSetupResult == SETUP_SUCCESS)
g_sInstVar.m_nSetupResult = LaunchINFInstall(hWnd);
}
return g_sInstVar.m_nSetupResult;
}
VOID CALLBACK Timer1Proc(HWND hwnd, // handle of window for timer messages
UINT uMsg, // WM_TIMER message
UINT idEvent, // timer identifier
DWORD dwTime) // current system time
{
static int nCount = 0;
if(nCount > 100)
nCount = 100;
// set the fake progressbar
SendMessage (g_sInstVar.m_hProgress, PBM_SETPOS, (WPARAM) nCount, 0);
nCount ++;
}
// This routine will do an installation based on those settings
// using the setupapi.dll
INT LaunchINFInstall( HWND hWnd )
{
TCHAR szInfFileName[MAX_PATH + 1];
TCHAR szInstallSection[MAX_TITLE];
BOOL bResult = FALSE;
// Context for my call back routine
HSPFILEQ hFileQueue;
HINF hInf;
PVOID pDefaultContext;
//
// Get inf handle
// must know where the inf is located
// SetupOpenInfFile will only look in windows\inf by default
//
lstrcpy(szInfFileName, g_sInstVar.m_szSourcePath);
lstrcat(szInfFileName, STR_DSCLIENT_INF);
hInf = SetupOpenInfFile(szInfFileName, // If path,needs full path, else looks in %windir%\inf
NULL, // Inf Type, matches Class in [Version] section SetupClass=SAMPLE
INF_STYLE_WIN4, // or INF_STYLE_OLDNT
NULL); // Line where error occurs if inf is has a problem
if (hInf == INVALID_HANDLE_VALUE)
return SETUP_ERROR;
//
// Create a Setup file queue and initialize the default Setup
// queue callback routine.
//
hFileQueue = SetupOpenFileQueue();
if(hFileQueue == INVALID_HANDLE_VALUE)
{
SetupCloseInfFile(hInf);
return SETUP_ERROR;
}
// using SetupInitDefaultQueueCallback.
SendMessage (g_sInstVar.m_hProgress, PBM_SETPOS, (WPARAM) 0, 0);
pDefaultContext = SetupInitDefaultQueueCallbackEx(hWnd, // HWND of owner window
NULL, // HWND of alternate progress dialog which receives
0, // Message sent to above window indicating a progress message
0, // DWORD Reserved
NULL); // PVOID Reserved
if(!pDefaultContext)
{
// Close the queue and the inf file and return
SetupCloseFileQueue(hFileQueue);
SetupCloseInfFile(hInf);
return SETUP_ERROR;
}
lstrcpy (szInstallSection, STR_INSTALL_SECTIONNT4);
//
// Queue file operations and commit the queue.
//
bResult = SetupInstallFilesFromInfSection(hInf, // HINF that has the directory ids set above
NULL, // layout.inf if you have one, this a convient
hFileQueue, // Queue to add files to
szInstallSection, // SectionName,
g_sInstVar.m_szSourcePath, // Path where the source files are located
SP_COPY_NEWER );
//
// All the files for each component are now in one queue
// now we commit it to start the copy ui, this way the
// user has one long copy progress dialog--and for a big install
// can go get the cup of coffee
if(bResult)
bResult = SetupCommitFileQueue(hWnd, // Owner
hFileQueue, // Queue with the file list
QueueCallbackProc, // This is our handler, it calls the default for us
pDefaultContext); // Pointer to resources allocated with SetupInitDefaultQueueCallback/Ex
if (!bResult || (g_sInstVar.m_nSetupResult == SETUP_CANCEL))
{
SetupTermDefaultQueueCallback(pDefaultContext);
SetupCloseFileQueue(hFileQueue);
SetupCloseInfFile(hInf);
if(g_sInstVar.m_nSetupResult == SETUP_CANCEL)
return SETUP_CANCEL;
else
return SETUP_ERROR;
}
//
// NOTE: you can do the entire install
// for a section with this api but in this case
// we build the file list conditionally and
// do only out ProductInstall section for registy stuff
// Also using SPINST_FILES will do the files
// as above but only one section at a time
// so the progress bar would keep completing and starting over
// SPINST_ALL does files, registry and inis
//
bResult = SetupInstallFromInfSection(hWnd,
hInf,
szInstallSection,
SPINST_INIFILES | SPINST_REGISTRY,
HKEY_LOCAL_MACHINE,
NULL, //m_szSourcePath, // Path where the source files are located
0, //SP_COPY_NEWER,
NULL, //(PSP_FILE_CALLBACK) QueueCallbackProc,
NULL, //&MyInstallData,
NULL,
NULL);
//
// We're done so free the context, close the queue,
// and release the inf handle
//
SetupTermDefaultQueueCallback(pDefaultContext);
SetupCloseFileQueue(hFileQueue);
SetupCloseInfFile(hInf);
if (g_sInstVar.m_bSysDlls)
{
//
// register OCX file
//
if(!RegisterOCX())
{
return SETUP_ERROR;
}
}
//
// The custom registry action after dsclient.inf by Chandana Surlu
//
DoDsclientReg();
SendMessage (g_sInstVar.m_hProgress, PBM_SETPOS, (WPARAM) 100, 0);
InstallFinish(FALSE);
return SETUP_SUCCESS;
}
/*---------------------------------------------------------------------*/
/*---------------------------------------------------------------------*/
UINT CALLBACK QueueCallbackProc(PVOID pDefaultContext,
UINT Notification,
UINT_PTR Param1,
UINT_PTR Param2)
{
static INT snFilesCopied;
// synchronizing user cancel
EnterCriticalSection(&g_sInstVar.m_oCriticalSection);
LeaveCriticalSection(&g_sInstVar.m_oCriticalSection);
//instaniate dialog first time
if (g_sInstVar.m_nSetupResult == SETUP_CANCEL)
{
SetLastError (ERROR_CANCELLED);
return FILEOP_ABORT;
}
switch (Notification)
{
case SPFILENOTIFY_STARTQUEUE:
case SPFILENOTIFY_ENDQUEUE:
return FILEOP_DOIT;
case SPFILENOTIFY_STARTCOPY:
// update file name item
SetWindowText(g_sInstVar.m_hFileNameItem,
((PFILEPATHS) Param1)->Target);
break;
case SPFILENOTIFY_ENDCOPY:
snFilesCopied++;
// update dialog file progress with message
if ((snFilesCopied + 1)>= NUM_FILES_TOTAL)
{
SendMessage (g_sInstVar.m_hProgress,
PBM_SETPOS,
(WPARAM) 100,
0);
}
else
{
SendMessage (g_sInstVar.m_hProgress,
PBM_SETPOS,
(WPARAM) ((float)snFilesCopied /
(float)NUM_FILES_TOTAL * 100),
0);
}
break;
default:
break;
}
return SetupDefaultQueueCallback(pDefaultContext,
Notification,
Param1,
Param2);
}
VOID InstallFinish(BOOL nShow)
{
if(nShow)
WinExec("grpconv -o", SW_SHOWNORMAL);
else
WinExec("grpconv -o", SW_HIDE);
}
// launch Inf file to install this component
BOOL LaunchProcess(LPTSTR lpCommandLine)
{
BOOL bResult = FALSE;
STARTUPINFO si;
PROCESS_INFORMATION pi;
// its console window will be invisible to the user.
ZeroMemory(&pi,sizeof(PROCESS_INFORMATION));
ZeroMemory(&si,sizeof(STARTUPINFO));
si.cb = sizeof (STARTUPINFO);
si.dwFlags = STARTF_USESHOWWINDOW;
si.wShowWindow = SW_HIDE; // HideWindow
if(CreateProcess( NULL,
lpCommandLine,
NULL,
NULL,
FALSE,
0,
NULL,
NULL,
&si,
&pi ) )
{
// wait to finish the runing setup process
WaitForSingleObject(pi.hProcess,INFINITE);
// close process handle
if (pi.hProcess && pi.hProcess != INVALID_HANDLE_VALUE)
{
CloseHandle (pi.hProcess) ;
}
if (pi.hThread && pi.hThread != INVALID_HANDLE_VALUE)
{
CloseHandle (pi.hThread) ;
}
bResult = TRUE;
}
return bResult;
}
// register OCX file
BOOL RegisterOCX()
{
TCHAR szSystem[MAX_PATH + 1];
TCHAR szTemp[MAX_PATH + 1];
TCHAR szCmdline[MAX_PATH + 1];
BOOL bSuccess = TRUE;
if(!GetSystemDirectory(szSystem, MAX_PATH))
return FALSE;
wsprintf(szTemp,
TEXT("%s%s%s"),
szSystem,
STR_REGISTER_REGSVR32_S_EXE,
szSystem);
//
// REVIEW_JEFFJON : we are not going to register it here
// Instead we are going to set the RunOnce regkey
// to register the dlls on reboot
//
if (g_sInstVar.m_bWabInst)
{
// register dsfolder.dll
wsprintf(szCmdline,
TEXT("%s%s %s%s %s%s %s%s %s%s"),
szTemp,
STR_REGISTER_DSFOLDER_DLL,
szSystem,
STR_REGISTER_DSUIEXT_DLL,
szSystem,
STR_REGISTER_DSQUERY_DLL,
szSystem,
STR_REGISTER_CMNQUERY_DLL,
szSystem,
STR_REGISTER_DSPROP_DLL);
ULONG WinError = 0;
HKEY RunOnceKey = NULL;
ULONG Size = 0;
ULONG Type = REG_SZ;
DWORD dwDisp = 0;
// open reg key
WinError = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
RUNONCE_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&RunOnceKey,
&dwDisp);
if (WinError == ERROR_SUCCESS)
{
UINT BufferSize = strlen(szCmdline);
BufferSize++;
WinError = RegSetValueEx( RunOnceKey,
REG_DSUI_VALUE,
0,
Type,
(PUCHAR)szCmdline,
BufferSize);
if (WinError != ERROR_SUCCESS && bSuccess)
{
bSuccess = FALSE;
}
//
// Run wabinst.exe
//
wsprintf(szCmdline,
TEXT("%s%s"),
szSystem,
STR_RUN_WABINST_EXE);
if (!LaunchProcess(szCmdline))
{
bSuccess = FALSE;
}
}
else
{
bSuccess = FALSE;
}
if (RunOnceKey)
{
RegCloseKey(RunOnceKey);
}
}
return bSuccess;
}
// The custom registry action after dsclient.inf by Chandana Surlu
VOID DoDsclientReg()
{
ULONG WinError = 0;
HKEY ProvidersKey = NULL;
ULONG Size = 0;
ULONG Type;
ULONG BufferSize = 0;
LPSTR StringToBeWritten = NULL;
DWORD dwDisp;
BOOL bSuccess = FALSE;
// open reg key
WinError = RegCreateKeyEx(HKEY_LOCAL_MACHINE,
SECURITY_PROVIDERS_KEY,
0,
NULL,
REG_OPTION_NON_VOLATILE,
KEY_ALL_ACCESS,
NULL,
&ProvidersKey,
&dwDisp);
if (WinError != ERROR_SUCCESS)
{
if (WinError == ERROR_FILE_NOT_FOUND)
{
BufferSize = sizeof(NEGOTIAT);
StringToBeWritten= (LPSTR) LocalAlloc(0,BufferSize);
if (StringToBeWritten)
{
strcpy (StringToBeWritten, NEGOTIAT);
bSuccess = TRUE;
}
}
}
else
{
WinError = RegQueryValueEx(ProvidersKey,
SECURITY_PROVIDERS_VALUE,
0,
&Type,
NULL,
&Size);
if ( WinError == ERROR_SUCCESS)
{
BufferSize = Size + sizeof(COMMA_BLANK) + sizeof(NEGOTIAT);
StringToBeWritten= (LPSTR) LocalAlloc(0,BufferSize);
if (StringToBeWritten)
{
WinError = RegQueryValueEx(ProvidersKey,
SECURITY_PROVIDERS_VALUE,
0,
&Type,
(PUCHAR) StringToBeWritten,
&Size);
if ( WinError == ERROR_SUCCESS)
{
if (NULL == strstr(StringToBeWritten, NEGOTIAT))
{
strcat (StringToBeWritten, COMMA_BLANK);
strcat (StringToBeWritten, NEGOTIAT);
bSuccess = TRUE;
}
}
}
}
else if (WinError == ERROR_FILE_NOT_FOUND)
{
BufferSize = sizeof(NEGOTIAT) + sizeof(CHAR);
StringToBeWritten= (LPSTR) LocalAlloc(0,BufferSize);
if (StringToBeWritten)
{
strcpy (StringToBeWritten, NEGOTIAT);
Type = REG_SZ;
bSuccess = TRUE;
}
}
}
if(bSuccess)
{
BufferSize = strlen(StringToBeWritten);
BufferSize++;
WinError = RegSetValueEx( ProvidersKey,
SECURITY_PROVIDERS_VALUE,
0,
Type,
(PUCHAR)StringToBeWritten,
BufferSize);
}
if (ProvidersKey)
{
RegCloseKey(ProvidersKey);
}
if (StringToBeWritten)
{
LocalFree(StringToBeWritten);
}
}
// The NTLMv2 custom action before dsclient.inf installation.
// Calling encrypted schannel installer to create dynamically a 128 bit secur32.dll
// to replace the old 56 bit secur32.dll.
BOOL DoEncSChannel()
{
FPGETENCSCHANNEL fpEncSChannel;
HINSTANCE hInst;
BYTE* pFileData;
DWORD dwSize = 0;
HANDLE hFile;
DWORD dwWritten;
BOOL bRet;
// load "instsec.dll"
hInst = LoadLibrary(STR_INSTSEC_DLL);
if(!hInst)
return TRUE;
// get the pointer of function "GetEncSChannel"
fpEncSChannel = (FPGETENCSCHANNEL) GetProcAddress(hInst, STR_GETENCSCHANNEL);
// calling GetEncSChannel to get the file data
if( !fpEncSChannel ||
fpEncSChannel(&pFileData, &dwSize) == FALSE ||
dwSize == 0)
{
FreeLibrary( hInst );
return TRUE;
}
// create file - "secur32.dll"
hFile = CreateFile(
STR_SECUR32_DLL, // pointer to name of the file "secur32.dll"
GENERIC_WRITE, // access (read-write) mode
0, // share mode
NULL, // pointer to security attributes
CREATE_ALWAYS, // how to create
FILE_ATTRIBUTE_NORMAL, // file attributes
NULL // handle to file with attributes to copy
);
if(hFile == INVALID_HANDLE_VALUE)
{
VirtualFree(pFileData, 0, MEM_RELEASE);
FreeLibrary( hInst );
return FALSE;
}
// write the file data to file "secur32.dll"
bRet = WriteFile(
hFile, // handle to file to write to
pFileData, // pointer to data to write to file
dwSize, // number of bytes to write
&dwWritten, // pointer to number of bytes written
NULL // pointer to structure for overlapped I/O
);
if(bRet && dwSize != dwWritten)
bRet = FALSE;
// clean memory
VirtualFree(pFileData, 0, MEM_RELEASE);
CloseHandle( hFile );
FreeLibrary( hInst );
return bRet;
}