#include #include DWORD DeleteGroupPolicyHistory( HKEY hkRoot ); LONG DeleteMachineUserPolicyHistoryKey(HANDLE hToken); #define MACHINE_USER_GP_KEY L"SOFTWARE\\Microsoft\\Windows\\CurrentVersion\\Group Policy" typedef struct _UNICODE_STRING { USHORT Length; USHORT MaximumLength; #ifdef MIDL_PASS [size_is(MaximumLength / 2), length_is((Length) / 2) ] USHORT * Buffer; #else // MIDL_PASS PWSTR Buffer; #endif // MIDL_PASS } UNICODE_STRING; typedef UNICODE_STRING *PUNICODE_STRING; LONG RtlConvertSidToUnicodeString( PUNICODE_STRING UnicodeString, PSID Sid, BOOLEAN AllocateDestinationString ); VOID RtlFreeUnicodeString( PUNICODE_STRING UnicodeString ); BOOL ProcessGPOs( void* ); void ReadPerfParams ( DWORD* pIterations, BOOL* pbDeleteHistory, BOOL* pbSkipFirstIteration, BOOL* pbUser, BOOL* pbMach, WCHAR* szPath ); void MeasurePerf( void* lpGPOInfo, HANDLE hToken, BOOL bMach ) { LARGE_INTEGER Freq; LARGE_INTEGER Start, Stop, Total; HKEY hkRoot; DWORD Iterations; BOOL bDeleteHistory; BOOL bSkipFirstIteration; BOOL bDoMach; BOOL bDoUser; WCHAR szPath[MAX_PATH+1]; ReadPerfParams ( &Iterations, &bDeleteHistory, &bSkipFirstIteration, &bDoUser, &bDoMach, szPath ); if ( ( bDoUser && !bMach ) || ( bDoMach && bMach ) ) { FILE* file; if ( bMach ) { lstrcat( szPath, L"MachPerf.log" ); } else { lstrcat( szPath, L"UserPerf.log" ); } file = _wfopen( szPath, L"a+" ); if ( file ) { DWORD n; fwprintf( file, L"\n" ); if ( RegOpenCurrentUser( KEY_READ, &hkRoot ) == ERROR_SUCCESS ) { QueryPerformanceFrequency( &Freq ); if ( !Freq.QuadPart ) { Freq.QuadPart = 1; } Total.QuadPart = 0; fprintf( file, "\nNew measurement: %d iterations\n\n", Iterations ); for ( n = 1; n <= Iterations; n++ ) { if ( bDeleteHistory ) { DeleteGroupPolicyHistory( hkRoot ); DeleteMachineUserPolicyHistoryKey(hToken); } QueryPerformanceCounter( &Start ); ProcessGPOs(lpGPOInfo); QueryPerformanceCounter( &Stop ); if ( bSkipFirstIteration && (1 == n) ) { bSkipFirstIteration = FALSE; n--; } else { Total.QuadPart += Stop.QuadPart - Start.QuadPart; } fwprintf( file, L"%d\t%f\t%f\n", n, ((double)Start.QuadPart / (double)Freq.QuadPart) * (double) 1000.0, ((double)Stop.QuadPart / (double)Freq.QuadPart) * (double) 1000.0 ); } fprintf( file, "Time = %f milliseconds per iteration\n\n", ((double)Total.QuadPart / (double)Freq.QuadPart) / (double)Iterations * (double) 1000.0 ); RegCloseKey( hkRoot ); } fclose( file ); } } } DWORD DeleteGroupPolicyHistory( HKEY hkRoot ) { return RegDelnode( hkRoot, L"Software\\Microsoft\\Windows\\CurrentVersion\\Group Policy\\History" ); } LONG DeleteMachineUserPolicyHistoryKey(HANDLE hToken) { UNICODE_STRING SidString; BOOL bStatus; DWORD Size; UCHAR Buffer[sizeof(TOKEN_USER) + sizeof(SID) + ((SID_MAX_SUB_AUTHORITIES-1) * sizeof(ULONG))]; LONG Status; HKEY hKeyGP; HKEY hKeyUserGP; PTOKEN_USER pTokenUser; hKeyGP = NULL; hKeyUserGP = NULL; Size = sizeof(Buffer); pTokenUser = (PTOKEN_USER) Buffer; bStatus = GetTokenInformation( hToken, TokenUser, pTokenUser, Size, &Size ); if ( ! bStatus ) { return GetLastError(); } Status = RtlConvertSidToUnicodeString( &SidString, pTokenUser->User.Sid, TRUE ); if (ERROR_SUCCESS != Status) { return Status; } Status = RegOpenKeyEx ( HKEY_LOCAL_MACHINE, MACHINE_USER_GP_KEY, 0, KEY_READ, &hKeyGP); if (ERROR_SUCCESS != Status) { goto cleanup; } Status = RegOpenKeyEx ( hKeyGP, SidString.Buffer, 0, KEY_ALL_ACCESS, &hKeyUserGP ); if (ERROR_SUCCESS != Status) { goto cleanup; } Status = RegDelnode( hKeyUserGP, L"History"); cleanup: if (hKeyGP) { RegCloseKey(hKeyGP); } if (hKeyUserGP) { RegCloseKey(hKeyUserGP); } RtlFreeUnicodeString( &SidString ); return Status; } void ReadPerfParams ( DWORD* pIterations, BOOL* pbDeleteHistory, BOOL* pbSkipFirstIteration, BOOL* pbUser, BOOL* pbMach, WCHAR* szPath ) { HKEY hKey; *pIterations = 5; *pbDeleteHistory = TRUE; *pbSkipFirstIteration = TRUE; *pbUser = TRUE; *pbMach = TRUE; lstrcpy( szPath, L"C:\\" ); if ( RegOpenKeyEx ( HKEY_LOCAL_MACHINE, L"SOFTWARE\\Microsoft\\Windows NT\\CurrentVersion\\Winlogon\\GPPerf", 0, KEY_READ, &hKey ) == ERROR_SUCCESS ) { DWORD dwType = 0; DWORD dwData = 0; DWORD cb = sizeof( DWORD ); if ( RegQueryValueEx( hKey, L"Iterations", 0, &dwType, (BYTE*)&dwData, &cb ) == ERROR_SUCCESS && dwType == REG_DWORD ) { *pIterations = dwData; } cb = sizeof( DWORD ); if ( RegQueryValueEx( hKey, L"DeleteHistory", 0, &dwType, (BYTE*)&dwData, &cb ) == ERROR_SUCCESS && dwType == REG_DWORD ) { *pbDeleteHistory = dwData; } cb = sizeof( DWORD ); if ( RegQueryValueEx( hKey, L"SkipFirst", 0, &dwType, (BYTE*)&dwData, &cb ) == ERROR_SUCCESS && dwType == REG_DWORD ) { *pbSkipFirstIteration = dwData; } cb = sizeof( DWORD ); if ( RegQueryValueEx( hKey, L"User", 0, &dwType, (BYTE*)&dwData, &cb ) == ERROR_SUCCESS && dwType == REG_DWORD ) { *pbUser = dwData; } cb = sizeof( DWORD ); if ( RegQueryValueEx( hKey, L"Machine", 0, &dwType, (BYTE*)&dwData, &cb ) == ERROR_SUCCESS && dwType == REG_DWORD ) { *pbMach = dwData; } cb = MAX_PATH; if ( !( RegQueryValueEx( hKey, L"Path", 0, &dwType, (BYTE*)szPath, &cb ) == ERROR_SUCCESS && dwType == REG_SZ ) ) { lstrcpy( szPath, L"C:\\" ); } RegCloseKey( hKey ); } }