//+--------------------------------------------------------------------------- // // Microsoft Windows // Copyright (C) Microsoft Corporation 1996-2001. // // File: wrapper.cpp // //---------------------------------------------------------------------------- #include "stdafx.h" #include "util.h" #include "resource.h" #include "winreg.h" #include "areaprog.h" #include "wrapper.h" #include "dsgetdc.h" typedef DWORD (WINAPI *PFNDSGETDCNAME)(LPCWSTR, LPCWSTR, GUID *, LPCWSTR, ULONG, PDOMAIN_CONTROLLER_INFOW *); typedef struct { LPCWSTR szProfile; LPCWSTR szDatabase; LPCWSTR szLog; AREA_INFORMATION Area; LPVOID *pHandle; PSCE_AREA_CALLBACK_ROUTINE pCallback; HANDLE hWndCallback; DWORD dwFlags; } ENGINEARGS; BOOL PostProgressArea( IN HANDLE CallbackHandle, IN AREA_INFORMATION Area, IN DWORD TotalTicks, IN DWORD CurrentTicks ); static BOOL bRangeSet=FALSE; CRITICAL_SECTION csOpenDatabase; #define OPEN_DATABASE_TIMEOUT INFINITE // // Helper functions to call the engine from a secondary thread: // DWORD WINAPI InspectSystemEx(LPVOID lpv) { if ( lpv == NULL ) return ERROR_INVALID_PARAMETER; ENGINEARGS *ea; SCESTATUS rc; ea = (ENGINEARGS *)lpv; DWORD dWarning=0; rc = SceAnalyzeSystem(NULL, ea->szProfile, ea->szDatabase, ea->szLog, SCE_UPDATE_DB|SCE_VERBOSE_LOG, ea->Area, ea->pCallback, ea->hWndCallback, &dWarning // this is required (by RPC) ); return rc; } // // call to SCE engine to apply the template // DWORD WINAPI ApplyTemplateEx(LPVOID lpv) { if ( lpv == NULL ) return ERROR_INVALID_PARAMETER; ENGINEARGS *ea; SCESTATUS rc; ea = (ENGINEARGS *)lpv; rc = SceConfigureSystem(NULL, ea->szProfile, ea->szDatabase, ea->szLog, SCE_OVERWRITE_DB|SCE_VERBOSE_LOG, ea->Area, ea->pCallback, ea->hWndCallback, NULL ); return rc; } WINBASEAPI BOOL WINAPI TryEnterCriticalSection( LPCRITICAL_SECTION lpCriticalSection ); /*------------------------------------------------------------------------------ Method: OpenDatabaseEx Synopsis: open database on a separate thread Arugments: Returns: History: a-mthoge 06-09-1998 - Added the _NT4BACK_PORT compile condition. ------------------------------------------------------------------------------*/ DWORD WINAPI OpenDatabaseEx(LPVOID lpv) { if ( lpv == NULL ) return ERROR_INVALID_PARAMETER; ENGINEARGS *ea; SCESTATUS rc=0; if (TryEnterCriticalSection(&csOpenDatabase)) { ea = (ENGINEARGS *)lpv; rc = SceOpenProfile(ea->szProfile, (SCE_FORMAT_TYPE) ea->dwFlags, // SCE_JET_FORMAT || SCE_JET_ANALYSIS_REQUIRED ea->pHandle ); LeaveCriticalSection(&csOpenDatabase); } else { rc = SCESTATUS_OTHER_ERROR; } return rc; } // // Assign a template to the system without configuring it // SCESTATUS AssignTemplate(LPCWSTR szTemplate, LPCWSTR szDatabase, BOOL bIncremental) { SCESTATUS rc; rc = SceConfigureSystem(NULL, szTemplate, szDatabase, NULL, (bIncremental ? SCE_UPDATE_DB : SCE_OVERWRITE_DB) | SCE_NO_CONFIG | SCE_VERBOSE_LOG, AREA_ALL, NULL, NULL, NULL ); return rc; } // // apply a template to the system // DWORD ApplyTemplate( LPCWSTR szProfile, LPCWSTR szDatabase, LPCWSTR szLogFile, AREA_INFORMATION Area ) { // Spawn a thread to call the engine & apply the profile, since this can // take a while and we want to stay responsive & have a change to provide // feedback. ENGINEARGS ea; HANDLE hThread=NULL; ea.szProfile = szProfile; ea.szDatabase = szDatabase; ea.szLog = szLogFile; ea.Area = Area; // // this is the progress call back dialog which // will be passed to SCE client stub for progress // callback // AreaProgress *ap = new AreaProgress; if ( ap ) { CString strTitle; CString strVerb; strTitle.LoadString(IDS_CONFIGURE_PROGRESS_TITLE); strVerb.LoadString(IDS_CONFIGURE_PROGRESS_VERB); ap->Create(IDD_ANALYZE_PROGRESS); ap->SetWindowText(strTitle); ap->SetDlgItemText(IDC_VERB,strVerb); ap->ShowWindow(SW_SHOW); bRangeSet = FALSE; } ea.pCallback = (PSCE_AREA_CALLBACK_ROUTINE)PostProgressArea; ea.hWndCallback = (HANDLE)ap; hThread = CreateThread(NULL,0,ApplyTemplateEx,&ea,0,NULL); DWORD dw=0; if ( hThread ) { MSG msg; DWORD dwTotalTicks=100; do { dw = MsgWaitForMultipleObjects(1,&hThread,0,INFINITE,QS_ALLINPUT); while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } while (WAIT_OBJECT_0 != dw); GetExitCodeThread(hThread,&dw); CloseHandle(hThread); } else { dw = GetLastError(); CString str; str.LoadString(IDS_CANT_CREATE_THREAD); AfxMessageBox(str); } // // free the dialog if it's created // if ( ap ) { if ( ap->GetSafeHwnd() ) ap->DestroyWindow(); delete ap; } return dw; } // // post progress // BOOL PostProgressArea( IN HANDLE CallbackHandle, IN AREA_INFORMATION Area, IN DWORD TotalTicks, IN DWORD CurrentTicks ) { if ( CallbackHandle ) { AreaProgress *ap = (AreaProgress *)CallbackHandle; ap->ShowWindow(SW_SHOW); if ( !bRangeSet ) { ap->SetMaxTicks(TotalTicks); bRangeSet = TRUE; } ap->SetCurTicks(CurrentTicks); ap->SetArea(Area); return TRUE; } else { return FALSE; } } // // inspect a system // DWORD InspectSystem( LPCWSTR szProfile, LPCWSTR szDatabase, LPCWSTR szLogFile, AREA_INFORMATION Area ) { // Spawn a thread to call the engine & inspect the system, since this can // take a while and we want to stay responsive & have a change to provide // feedback. ENGINEARGS ea; HANDLE hThread=NULL; ea.szProfile = szProfile; ea.szDatabase = szDatabase; ea.szLog = szLogFile; ea.Area = Area; AreaProgress *ap = new AreaProgress; if ( ap ) { ap->Create(IDD_ANALYZE_PROGRESS); ap->ShowWindow(SW_SHOW); bRangeSet = FALSE; } ea.pCallback = (PSCE_AREA_CALLBACK_ROUTINE)PostProgressArea; ea.hWndCallback = (HANDLE)ap; // return InspectSystemEx(&ea); hThread = CreateThread(NULL,0,InspectSystemEx,&ea,0,NULL); if (!hThread) { DWORD rc = GetLastError(); CString str; str.LoadString(IDS_CANT_CREATE_THREAD); AfxMessageBox(str); // Display an error if ( ap ) { if ( ap->GetSafeHwnd() ) ap->DestroyWindow(); delete ap; } return rc; } MSG msg; DWORD dw=0; DWORD dwTotalTicks=100; int n = 0; do { dw = MsgWaitForMultipleObjects(1,&hThread,0,100,QS_ALLINPUT); while (PeekMessage(&msg,NULL,0,0,PM_REMOVE)) { TranslateMessage(&msg); DispatchMessage(&msg); } } while (WAIT_OBJECT_0 != dw); GetExitCodeThread(hThread,&dw); CloseHandle(hThread); if ( ap ) { if ( ap->GetSafeHwnd() ) ap->DestroyWindow(); delete ap; } return dw; } BOOL GetProfileDescription(LPCTSTR ProfileName, LPWSTR* Description) // Description must be freed by LocalFree // This should only be called for INF format profiles { PVOID hProfile=NULL; SCESTATUS rc; if (EngineOpenProfile(ProfileName,OPEN_PROFILE_CONFIGURE,&hProfile) == SCESTATUS_SUCCESS) { rc = SceGetScpProfileDescription( hProfile, Description); SceCloseProfile(&hProfile); if ( rc == SCESTATUS_SUCCESS ) { return(TRUE); } else { return(FALSE); } } else { return FALSE; } } SCESTATUS EngineOpenProfile( LPCWSTR FileName OPTIONAL, int format, PVOID* hProfile ) { SCESTATUS status; ENGINEARGS ea; DWORD dw; HANDLE hThread=NULL; CString str; if ( !hProfile ) { // do not check !FileName because it's optional now return SCESTATUS_PROFILE_NOT_FOUND; } if ( (OPEN_PROFILE_LOCALPOL != format) && !FileName ) { return SCESTATUS_PROFILE_NOT_FOUND; } ZeroMemory(&ea, sizeof( ENGINEARGS ) ); // This is multithreaded for responsiveness, since a // crashed jet database can take forever and a day to open. // If we can open it quickly (where quickly is defined as within // OPEN_DATABASE_TIMEOUT milliseconds then if ( (OPEN_PROFILE_ANALYSIS == format) || (OPEN_PROFILE_LOCALPOL == format)) {// JET { ea.szProfile = FileName; ea.pHandle = hProfile; if (OPEN_PROFILE_LOCALPOL == format) { ea.dwFlags = SCE_JET_FORMAT; } else { ea.dwFlags = SCE_JET_ANALYSIS_REQUIRED; } #if SPAWN_OPEN_DATABASE_THREAD hThread = CreateThread(NULL,0,OpenDatabaseEx,&ea,0,NULL); if ( hThread ) { dw = MsgWaitForMultipleObjects(1,&hThread,0,OPEN_DATABASE_TIMEOUT,0); if (WAIT_TIMEOUT == dw) { status = SCESTATUS_OTHER_ERROR; } else { GetExitCodeThread(hThread,&status); } CloseHandle(hThread); } else { status = GetLastError(); } #else status = OpenDatabaseEx(&ea); #endif if( status != SCESTATUS_SUCCESS && *hProfile ){ status = SCESTATUS_INVALID_DATA; } } else { // INF status = SceOpenProfile( FileName, SCE_INF_FORMAT, hProfile ); } if ( status != SCESTATUS_SUCCESS ){ *hProfile = NULL; } return status; } void EngineCloseProfile(PVOID* hProfile) { if ( hProfile ) { SceCloseProfile(hProfile); } *hProfile = NULL; } BOOL EngineGetDescription(PVOID hProfile, LPWSTR* Desc) { if ( SceGetScpProfileDescription( hProfile, Desc) != SCESTATUS_SUCCESS ) { return FALSE; } else { return TRUE; } } BOOL IsDomainController( LPCTSTR pszComputer ) { // // for remote computers, connect to the remote registry // currently this api only works for local computer // SCE_SERVER_TYPE ServerType = SCESVR_UNKNOWN; SCESTATUS rc = SceGetServerProductType((LPTSTR)pszComputer, &ServerType); return ( (SCESTATUS_SUCCESS == rc) && (SCESVR_DC_WITH_DS == ServerType) ); }