//+------------------------------------------------------------------ // // 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 #include #include #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; }