X-Git-Url: https://git.dogcows.com/gitweb?p=chaz%2Fthecheat;a=blobdiff_plain;f=CheatServer.m;fp=CheatServer.m;h=2a8ed8ca899879aeac5835398396c425bacffc03;hp=0000000000000000000000000000000000000000;hb=42cf7bbe564d70233a0d73baee613f209eb00eb6;hpb=2d60a59a8ad195dd0af8f90c8d5b74a69ce7f4fa diff --git a/CheatServer.m b/CheatServer.m new file mode 100644 index 0000000..2a8ed8c --- /dev/null +++ b/CheatServer.m @@ -0,0 +1,2035 @@ + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Project: The Cheat +// +// File: CheatServer.m +// Created: Sun Sep 07 2003 +// +// Copyright: 2003 Chaz McGarvey. All rights reserved. +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#import "CheatServer.h" + +#import "SearchResults.h" + +#include +#include + + +// Internal Functions +BOOL inline compare_float( float a, float b ); +BOOL inline compare_double( double a, double b ); + + +@implementation CheatServer + + ++ (NSConnection *)serverWithDelegate:(id)delegate socket:(int)sock +{ + NSPort *rPort = [NSPort port], *sPort = [NSPort port]; + NSConnection *connection; + NSArray *array; + + connection = [[NSConnection alloc] initWithReceivePort:rPort sendPort:sPort]; + [connection setRootObject:delegate]; + + array = [NSArray arrayWithObjects:sPort, rPort, [NSNumber numberWithInt:sock], nil]; + [NSThread detachNewThreadSelector:@selector(serverThread:) toTarget:self withObject:array]; + + return [connection autorelease]; +} + ++ (void)serverThread:(NSArray *)array +{ + NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; + NSConnection *connection = [NSConnection connectionWithReceivePort:[array objectAtIndex:0] sendPort:[array objectAtIndex:1]]; + CheatServer *object = [[self alloc] initWithRootProxy:[connection rootProxy]]; + + [object handleSocket:[[array objectAtIndex:2] intValue]]; + [object run]; + + [object release]; + [pool release]; +} + + +- (id)initWithRootProxy:(id)proxy +{ + if ( self = [super init] ) + { + NSNotificationCenter *nc = [[NSWorkspace sharedWorkspace] notificationCenter]; + + rootProxy = proxy; + + [nc addObserver:self selector:@selector(processListChanged:) name:@"NSWorkspaceDidLaunchApplicationNotification" object:nil]; + [nc addObserver:self selector:@selector(processListChanged:) name:@"NSWorkspaceDidTerminateApplicationNotification" object:nil]; + + [self setPID:[rootProxy serverFirstProcess]]; + + processPaused = NO; + + searchResults = [[NSMutableArray alloc] init]; + searchResultsUndone = [[NSMutableArray alloc] init]; + } + + return self; +} + + +- (void)handleSocket:(int)sock +{ + struct sockaddr identifier; + int addrLen = sizeof(identifier); + + NSString *address; + char *addressCString; + + sockfd = sock; + + if ( getpeername( sockfd, &identifier, &addrLen ) == -1 ) + { + NSLog( @"ERROR: getpeername() failed" ); + } + + if ( identifier.sa_family == AF_INET ) + { + struct sockaddr_in addr; + + addrLen = sizeof(addr); + + if ( getpeername( sockfd, (struct sockaddr *)(&addr), &addrLen ) == -1 ) + { + NSLog( @"ERROR: getpeername() failed" ); + } + + if ( (addressCString = inet_ntoa( addr.sin_addr )) == NULL ) + { + NSLog( @"ERROR: inet_ntoa() failed" ); + } + + address = [NSString stringWithCString:addressCString]; + } + else + { + struct sockaddr_un addr; + + addrLen = sizeof(addr); + + if ( getpeername( sockfd, (struct sockaddr *)(&addr), &addrLen ) == -1 ) + { + NSLog( @"ERROR: getpeername() failed" ); + } + + NSLog( @"client connection: %s", addr.sun_path ); + + address = [NSString stringWithString:@"127.0.0.1"]; + } + + [rootProxy server:self connectedWithSocket:sockfd]; + + [self setAddress:address]; + [self setAction:nil]; +} + +- (void)run +{ + struct timeval tv; + fd_set fdset, master; + int numfds; + + int result; + + PacketHeader header; + char *data = NULL; + + tv.tv_sec = 2; + tv.tv_usec = 0; + + FD_ZERO( &fdset ); + FD_ZERO( &master ); + FD_SET( sockfd, &master ); + + numfds = sockfd + 1; + + NSLog( @"SERVER start" ); + + for (;;) + { + fdset = master; + + select( numfds, &fdset, NULL, NULL, &tv ); + + if ( FD_ISSET( sockfd, &fdset ) ) + { + if ( (result = ReadBuffer( sockfd, (char *)(&header), sizeof(header) )) != sizeof(header) ) + { + break; + } + + if ( !VerifyChecksum( header.checksum ) ) + { + NSLog( @"checksum failed" ); + } + + if ( header.size != 0 ) + { + if ( (data = (char *)malloc( header.size )) == NULL ) + { + NSLog( @"failed to allocate buffer for reading a network packet" ); + break; + } + + if ( (result = ReadBuffer( sockfd, data, header.size )) != header.size ) + { + NSLog( @"failed to read the data of a network packet" ); + free( data ); + break; + } + } + + NSLog( @"SERVER message %i/%i/%i", header.checksum, header.function, header.size ); + + switch ( header.function ) + { + case 1: + [self sendProcessList]; + break; + + case 3: + [self handleClearSearch]; + break; + + case 5: + [self handleSearch:data size:header.size]; + break; + + case 8: + [self handleChange:data size:header.size]; + break; + + case 10: + [self handlePauseTarget]; + break; + + case 14: + [self handleUndo]; + break; + + case 16: + [self handleRedo]; + break; + + case 18: + [self handleSetTargetPID:data size:header.size]; + break; + + } + + if ( header.size != 0 ) + { + free( data ); + } + } + } + + close( sockfd ); + + NSLog( @"SERVER close" ); + + [rootProxy serverDisconnected:self]; +} + + +- (void)setAddress:(NSString *)address +{ + [rootProxy server:self changedAddress:address]; +} + +- (void)setAction:(NSString *)action +{ + if ( action == nil ) + { + [rootProxy server:self changedAction:@"Idle"]; + } + else + { + [rootProxy server:self changedAction:action]; + } +} + +- (void)firstSearchString8bit:(char const *)value size:(int)vsize +{ + kern_return_t result; + + vm_address_t address = 0x0; + vm_size_t size = 0; + vm_region_basic_info_data_t info; + mach_msg_type_number_t infoCnt = 8; + mach_port_t object_name = 0; + + char *data; + vm_size_t dataLength; + + TCaddress *results = NULL; + int resultsAmount = 0; + + NSLog( @"string search: %s", value ); + + for (;;) + { + if ( (result = vm_region( processTask, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name )) != KERN_SUCCESS ) + { + if ( result != KERN_INVALID_ADDRESS ) + { + NSLog( @"vm_region returned error: %i", result ); + } + break; + } + + if ( (info.protection & VM_PROT_READ) && (info.protection & VM_PROT_WRITE)) + { + data = (char *)malloc( size ); + dataLength = size; + + if ( (result = vm_read_overwrite( processTask, address, size, (vm_address_t)data, &dataLength )) != KERN_SUCCESS && result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + free( data ); + break; + } + + if ( result == KERN_SUCCESS ) + { + int i, top = dataLength - vsize; + + if ( (results = realloc( results, TCAddressSize*resultsAmount + dataLength )) == NULL ) + { + NSLog( @"ERROR: could not expand buffer" ); + exit(0); + } + + for ( i = 0; i < top; i++ ) + { + if ( strncmp( value, data+i, vsize ) == 0 ) + { + results[resultsAmount++] = (TCaddress)address + i; + } + } + } + + free( data ); + } + + address += size; + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_8_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)firstSearchIntegerChar:(int8_t)value +{ + kern_return_t result; + + vm_address_t address = 0x0; + vm_size_t size = 0; + vm_region_basic_info_data_t info; + mach_msg_type_number_t infoCnt = 8; + mach_port_t object_name = 0; + + int8_t *data; + vm_size_t dataLength; + + TCaddress *results = NULL; + int resultsAmount = 0; + + for (;;) + { + if ( (result = vm_region( processTask, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name )) != KERN_SUCCESS ) + { + if ( result != KERN_INVALID_ADDRESS ) + { + NSLog( @"vm_region returned error: %i", result ); + } + break; + } + + if ( (info.protection & VM_PROT_READ) && (info.protection & VM_PROT_WRITE)) + { + data = (int8_t *)malloc( size ); + dataLength = size; + + if ( (result = vm_read_overwrite( processTask, address, size, (vm_address_t)data, &dataLength )) != KERN_SUCCESS && result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + free( data ); + break; + } + + if ( result == KERN_SUCCESS ) + { + int i; + + if ( (results = (TCaddress *)realloc( results, TCAddressSize*resultsAmount + TCAddressSize*dataLength )) == NULL ) + { + NSLog( @"ERROR: could not expand buffer" ); + exit(0); + } + + for ( i = 0; i < dataLength; i++ ) + { + if ( *(data+i) == value ) + { + results[resultsAmount++] = (TCaddress)address + i; + } + } + } + + free( data ); + } + + address += size; + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_8_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)firstSearchIntegerShort:(int16_t)value +{ + kern_return_t result; + + vm_address_t address = 0x0; + vm_size_t size = 0; + vm_region_basic_info_data_t info; + mach_msg_type_number_t infoCnt = 8; + mach_port_t object_name = 0; + + int16_t *data; + vm_size_t dataLength; + + TCaddress *results = NULL; + int resultsAmount = 0; + + for (;;) + { + if ( (result = vm_region( processTask, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name )) != KERN_SUCCESS ) + { + if ( result != KERN_INVALID_ADDRESS ) + { + NSLog( @"vm_region returned error: %i", result ); + } + break; + } + + if ( (info.protection & VM_PROT_READ) && (info.protection & VM_PROT_WRITE)) + { + data = (int16_t *)malloc( size ); + dataLength = size; + + if ( (result = vm_read_overwrite( processTask, address, size, (vm_address_t)data, &dataLength )) != KERN_SUCCESS && result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + free( data ); + break; + } + + if ( result == KERN_SUCCESS ) + { + int i, top = dataLength / sizeof(value); + + if ( (results = (TCaddress *)realloc( results, TCAddressSize*resultsAmount + 2*dataLength )) == NULL ) + { + NSLog( @"ERROR: could not expand buffer" ); + exit(0); + } + + for ( i = 0; i < top; i++ ) + { + if ( *(data+i) == value ) + { + results[resultsAmount++] = (TCaddress)address + i * sizeof(value); + } + } + } + + free( data ); + } + + address += size; + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_16_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)firstSearchIntegerLong:(int32_t)value +{ + kern_return_t result; + + vm_address_t address = 0x0; + vm_size_t size = 0; + vm_region_basic_info_data_t info; + mach_msg_type_number_t infoCnt = 8; + mach_port_t object_name = 0; + + int32_t *data; + vm_size_t dataLength; + + TCaddress *results = NULL; + int resultsAmount = 0; + + unsigned zone_count = 10; + vm_address_t *zones = (vm_address_t *)malloc( zone_count * sizeof(vm_address_t) ); + //memory_reader_t reader; + + if ( (result = malloc_get_all_zones( processTask, NULL, &zones, &zone_count )) != KERN_SUCCESS ) + { + NSLog( @"malloc_get_all_zones error: %i", result ); + } + else + { + //address = zones[0]; + + /*int i; + + for ( i = 0; i < 10; i++ ) + { + NSLog( @"malloc_get_all_zones[%i] = %X", i, (vm_address_t)zones[i] ); + }*/ + } + + for (;;) + { + if ( (result = vm_region( processTask, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name )) != KERN_SUCCESS ) + { + if ( result != KERN_INVALID_ADDRESS ) + { + NSLog( @"vm_region returned error: %i", result ); + } + break; + } + + if ( (info.protection & VM_PROT_READ) && (info.protection & VM_PROT_WRITE) ) + { + data = (int32_t *)malloc( size ); + dataLength = size; + + NSLog( @"address: %.8X size: %i", address, size ); + + if ( (result = vm_read_overwrite( processTask, address, size, (vm_address_t)data, &dataLength )) != KERN_SUCCESS && result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + free( data ); + break; + } + + if ( result == KERN_SUCCESS ) + { + int i, top = dataLength / sizeof(value); + + if ( (results = (TCaddress *)realloc( results, TCAddressSize*resultsAmount + dataLength )) == NULL ) + { + NSLog( @"ERROR: could not expand buffer" ); + exit(0); + } + + for ( i = 0; i < top; i++ ) + { + if ( *(data+i) == value ) + { + results[resultsAmount++] = (TCaddress)address + i * sizeof(value); + } + } + } + + free( data ); + } + + address += size; + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_32_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + + +- (void)firstSearchDecimalFloat:(float)value +{ + kern_return_t result; + + vm_address_t address = 0x0; + vm_size_t size = 0; + vm_region_basic_info_data_t info; + mach_msg_type_number_t infoCnt = 8; + mach_port_t object_name = 0; + + float *data; + vm_size_t dataLength; + + TCaddress *results = NULL; + int resultsAmount = 0; + + for (;;) + { + if ( (result = vm_region( processTask, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name )) != KERN_SUCCESS ) + { + if ( result != KERN_INVALID_ADDRESS ) + { + NSLog( @"vm_region returned error: %i", result ); + } + break; + } + + if ( (info.protection & VM_PROT_READ) && (info.protection & VM_PROT_WRITE)) + { + data = (float *)malloc( size ); + dataLength = size; + + if ( (result = vm_read_overwrite( processTask, address, size, (vm_address_t)data, &dataLength )) != KERN_SUCCESS && result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + free( data ); + break; + } + + if ( result == KERN_SUCCESS ) + { + int i, top = dataLength / sizeof(value); + + if ( (results = realloc( results, TCAddressSize*resultsAmount + dataLength )) == NULL ) + { + NSLog( @"ERROR: could not expand buffer" ); + exit(0); + } + + for ( i = 0; i < top; i++ ) + { + if ( compare_float( *(data+i), value ) ) + { + results[resultsAmount++] = (TCaddress)address + i * sizeof(value); + } + } + } + + free( data ); + } + + address += size; + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_DECIMAL size:SIZE_32_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)firstSearchDecimalDouble:(double)value +{ + kern_return_t result; + + vm_address_t address = 0x0; + vm_size_t size = 0; + vm_region_basic_info_data_t info; + mach_msg_type_number_t infoCnt = 8; + mach_port_t object_name = 0; + + double *data; + vm_size_t dataLength; + + TCaddress *results = NULL; + int resultsAmount = 0; + + NSLog( @"float search" ); + + for (;;) + { + if ( (result = vm_region( processTask, &address, &size, VM_REGION_BASIC_INFO, (vm_region_info_t)(&info), &infoCnt, &object_name )) != KERN_SUCCESS ) + { + if ( result != KERN_INVALID_ADDRESS ) + { + NSLog( @"vm_region returned error: %i", result ); + } + break; + } + + if ( (info.protection & VM_PROT_READ) && (info.protection & VM_PROT_WRITE)) + { + data = (double *)malloc( size ); + dataLength = size; + + if ( (result = vm_read_overwrite( processTask, address, size, (vm_address_t)data, &dataLength )) != KERN_SUCCESS && result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + free( data ); + break; + } + + if ( result == KERN_SUCCESS ) + { + int i, top = dataLength / sizeof(value); + + if ( (results = realloc( results, TCAddressSize*resultsAmount + dataLength )) == NULL ) + { + NSLog( @"ERROR: could not expand buffer" ); + exit(0); + } + + for ( i = 0; i < top; i++ ) + { + if ( compare_double( *(data+i), value ) ) + { + results[resultsAmount++] = (TCaddress)address + i * sizeof(value); + } + } + } + + free( data ); + } + + address += size; + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_DECIMAL size:SIZE_64_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + + +- (void)searchString8bit:(char const *)value size:(int)vsize +{ + kern_return_t result; + + int8_t data; + vm_size_t dataLength; + + TCaddress *results; + int resultsAmount = 0; + + SearchResults *lastResults = [searchResults lastObject]; + TCaddress *lastResultsData = [lastResults data]; + int i, lastResultsAmount = [lastResults amount]; + + if ( [lastResults type] != TYPE_INTEGER || [lastResults size] != SIZE_8_BIT ) + { + [self sendError:@"This search is incompatible with the previous search." fatal:NO]; + return; + } + + if ( (results = (TCaddress *)malloc( TCAddressSize*lastResultsAmount )) == NULL ) + { + NSLog( @"ERROR: could not create buffer" ); + + [self sendError:@"The server cancelled the search because it ran out of memory." fatal:NO]; + return; + } + + for ( i = 0; i < lastResultsAmount; i++ ) + { + TCaddress address = lastResultsData[i]; + + dataLength = sizeof(data); + + if ( (result = vm_read_overwrite( processTask, address, sizeof(data), (vm_address_t)(&data), &dataLength )) == KERN_SUCCESS ) + { + if ( data == value[0] ) + { + results[resultsAmount++] = address; + } + } + else + { + if ( result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + break; + } + } + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_8_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)searchIntegerChar:(int8_t)value +{ + kern_return_t result; + + int8_t data; + vm_size_t dataLength; + + TCaddress *results; + int resultsAmount = 0; + + SearchResults *lastResults = [searchResults lastObject]; + TCaddress *lastResultsData = [lastResults data]; + int i, lastResultsAmount = [lastResults amount]; + + if ( [lastResults type] != TYPE_INTEGER || [lastResults size] != SIZE_8_BIT ) + { + [self sendError:@"This search is incompatible with the previous search." fatal:NO]; + return; + } + + if ( (results = (TCaddress *)malloc( TCAddressSize*lastResultsAmount )) == NULL ) + { + NSLog( @"ERROR: could not create buffer" ); + + [self sendError:@"The server cancelled the search because it ran out of memory." fatal:NO]; + return; + } + + for ( i = 0; i < lastResultsAmount; i++ ) + { + TCaddress address = lastResultsData[i]; + + dataLength = sizeof(data); + + if ( (result = vm_read_overwrite( processTask, address, sizeof(data), (vm_address_t)(&data), &dataLength )) == KERN_SUCCESS ) + { + if ( data == value ) + { + results[resultsAmount++] = address; + } + } + else + { + if ( result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + break; + } + } + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_8_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)searchIntegerShort:(int16_t)value +{ + kern_return_t result; + + int16_t data; + vm_size_t dataLength; + + TCaddress *results; + int resultsAmount = 0; + + SearchResults *lastResults = [searchResults lastObject]; + TCaddress *lastResultsData = [lastResults data]; + int i, lastResultsAmount = [lastResults amount]; + + if ( [lastResults type] != TYPE_INTEGER || [lastResults size] != SIZE_16_BIT ) + { + [self sendError:@"This search is incompatible with the previous search." fatal:NO]; + return; + } + + if ( (results = (TCaddress *)malloc( TCAddressSize*lastResultsAmount )) == NULL ) + { + NSLog( @"ERROR: could not create buffer" ); + + [self sendError:@"The server cancelled the search because it ran out of memory." fatal:NO]; + return; + } + + for ( i = 0; i < lastResultsAmount; i++ ) + { + TCaddress address = lastResultsData[i]; + + dataLength = sizeof(data); + + if ( (result = vm_read_overwrite( processTask, address, sizeof(data), (vm_address_t)(&data), &dataLength )) == KERN_SUCCESS ) + { + if ( data == value ) + { + results[resultsAmount++] = address; + } + } + else + { + if ( result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + break; + } + } + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_16_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)searchIntegerLong:(int32_t)value +{ + kern_return_t result; + + int32_t data; + vm_size_t dataLength; + + TCaddress *results; + int resultsAmount = 0; + + SearchResults *lastResults = [searchResults lastObject]; + TCaddress *lastResultsData = [lastResults data]; + int i, lastResultsAmount = [lastResults amount]; + + if ( [lastResults type] != TYPE_INTEGER || [lastResults size] != SIZE_32_BIT ) + { + [self sendError:@"This search is incompatible with the previous search." fatal:NO]; + return; + } + + if ( (results = (TCaddress *)malloc( TCAddressSize*lastResultsAmount )) == NULL ) + { + NSLog( @"ERROR: could not create buffer" ); + + [self sendError:@"The server cancelled the search because it ran out of memory." fatal:NO]; + return; + } + + for ( i = 0; i < lastResultsAmount; i++ ) + { + TCaddress address = lastResultsData[i]; + + dataLength = sizeof(data); + + if ( (result = vm_read_overwrite( processTask, address, sizeof(data), (vm_address_t)(&data), &dataLength )) == KERN_SUCCESS ) + { + if ( data == value ) + { + results[resultsAmount++] = address; + } + } + else + { + if ( result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + break; + } + } + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_INTEGER size:SIZE_32_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)searchDecimalFloat:(float)value +{ + kern_return_t result; + + float data; + vm_size_t dataLength; + + TCaddress *results; + int resultsAmount = 0; + + SearchResults *lastResults = [searchResults lastObject]; + TCaddress *lastResultsData = [lastResults data]; + int i, lastResultsAmount = [lastResults amount]; + + if ( [lastResults type] != TYPE_DECIMAL || [lastResults size] != SIZE_32_BIT ) + { + [self sendError:@"This search is incompatible with the previous search." fatal:NO]; + return; + } + + if ( (results = (TCaddress *)malloc( TCAddressSize*lastResultsAmount )) == NULL ) + { + NSLog( @"ERROR: could not create buffer" ); + + [self sendError:@"The server cancelled the search because it ran out of memory." fatal:NO]; + return; + } + + for ( i = 0; i < lastResultsAmount; i++ ) + { + TCaddress address = lastResultsData[i]; + + dataLength = sizeof(data); + + if ( (result = vm_read_overwrite( processTask, address, sizeof(data), (vm_address_t)(&data), &dataLength )) == KERN_SUCCESS ) + { + if ( compare_float( data, value ) ) + { + results[resultsAmount++] = address; + } + } + else + { + if ( result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + break; + } + } + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_DECIMAL size:SIZE_32_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + +- (void)searchDecimalDouble:(double)value +{ + kern_return_t result; + + double data; + vm_size_t dataLength; + + TCaddress *results; + int resultsAmount = 0; + + SearchResults *lastResults = [searchResults lastObject]; + TCaddress *lastResultsData = [lastResults data]; + int i, lastResultsAmount = [lastResults amount]; + + if ( [lastResults type] != TYPE_DECIMAL || [lastResults size] != SIZE_64_BIT ) + { + [self sendError:@"This search is incompatible with the previous search." fatal:NO]; + return; + } + + if ( (results = (TCaddress *)malloc( TCAddressSize*lastResultsAmount )) == NULL ) + { + NSLog( @"ERROR: could not create buffer" ); + + [self sendError:@"The server cancelled the search because it ran out of memory." fatal:NO]; + return; + } + + for ( i = 0; i < lastResultsAmount; i++ ) + { + TCaddress address = lastResultsData[i]; + + dataLength = sizeof(data); + + if ( (result = vm_read_overwrite( processTask, address, sizeof(data), (vm_address_t)(&data), &dataLength )) == KERN_SUCCESS ) + { + if ( compare_double( data, value ) ) + { + results[resultsAmount++] = address; + } + } + else + { + if ( result != KERN_PROTECTION_FAILURE ) + { + NSLog( @"vm_read_overwrite returned error: %i", result ); + break; + } + } + } + + realloc( results, TCAddressSize*resultsAmount ); + [searchResults addObject:[SearchResults resultsWithType:TYPE_DECIMAL size:SIZE_64_BIT data:results amount:resultsAmount]]; + + NSLog( @"found %i of %i", resultsAmount, value ); +} + + +- (void)changeString8bit:(char const *)value size:(int)vsize addresses:(TCaddress *)addresses count:(int)count +{ + int failCount = 0; + int i; + + NSLog( @"change string: %s", value ); + + for ( i = 0; i < count; i++ ) + { + if ( vm_write( processTask, (vm_address_t)addresses[i], (vm_offset_t)value, vsize ) != KERN_SUCCESS ) + { + failCount++; + } + } + + if ( failCount > 0 ) + { + [self sendError:[NSString stringWithFormat:@"%i of the selected variables could not be changed.", failCount] fatal:NO]; + } +} + +- (void)changeIntegerChar:(int8_t)value addresses:(TCaddress *)addresses count:(int)count +{ + int failCount = 0; + int i; + + for ( i = 0; i < count; i++ ) + { + if ( vm_write( processTask, (vm_address_t)addresses[i], (vm_offset_t)(&value), sizeof(value) ) != KERN_SUCCESS ) + { + failCount++; + } + } + + if ( failCount > 0 ) + { + [self sendError:[NSString stringWithFormat:@"%i of the selected variables could not be changed.", failCount] fatal:NO]; + } +} + +- (void)changeIntegerShort:(int16_t)value addresses:(TCaddress *)addresses count:(int)count +{ + int failCount = 0; + int i; + + for ( i = 0; i < count; i++ ) + { + if ( vm_write( processTask, (vm_address_t)addresses[i], (vm_offset_t)(&value), sizeof(value) ) != KERN_SUCCESS ) + { + failCount++; + } + } + + if ( failCount > 0 ) + { + [self sendError:[NSString stringWithFormat:@"%i of the selected variables could not be changed.", failCount] fatal:NO]; + } +} + +- (void)changeIntegerLong:(int32_t)value addresses:(TCaddress *)addresses count:(int)count +{ + int failCount = 0; + int i; + + for ( i = 0; i < count; i++ ) + { + if ( vm_write( processTask, (vm_address_t)addresses[i], (vm_offset_t)(&value), sizeof(value) ) != KERN_SUCCESS ) + { + failCount++; + } + } + + if ( failCount > 0 ) + { + [self sendError:[NSString stringWithFormat:@"%i of the selected variables could not be changed.", failCount] fatal:NO]; + } +} + +- (void)changeDecimalFloat:(float)value addresses:(TCaddress *)addresses count:(int)count +{ + int failCount = 0; + int i; + + for ( i = 0; i < count; i++ ) + { + if ( vm_write( processTask, (vm_address_t)addresses[i], (vm_offset_t)(&value), sizeof(value) ) != KERN_SUCCESS ) + { + failCount++; + } + } + + if ( failCount > 0 ) + { + [self sendError:[NSString stringWithFormat:@"%i of the selected variables could not be changed.", failCount] fatal:NO]; + } +} + +- (void)changeDecimalDouble:(double)value addresses:(TCaddress *)addresses count:(int)count +{ + int failCount = 0; + int i; + + for ( i = 0; i < count; i++ ) + { + if ( vm_write( processTask, (vm_address_t)addresses[i], (vm_offset_t)(&value), sizeof(value) ) != KERN_SUCCESS ) + { + failCount++; + } + } + + if ( failCount > 0 ) + { + [self sendError:[NSString stringWithFormat:@"%i of the selected variables could not be changed.", failCount] fatal:NO]; + } +} + + +- (void)sendProcessList +{ + NSArray *processList = [rootProxy serverProcessList]; + + NSNumber *pid; + u_int32_t pidNum; + NSString *name; + + PacketHeader header; + + char *buffer, *ptr; + + // PROCESS COUNT + int length = sizeof(u_int32_t); + int lengthAfter; + + u_int32_t processCount = [processList count]; + + int i, max = processCount; + + header.checksum = RandomChecksum(); + header.function = 2; + + for ( i = 0; i < max; i++ ) + { + pid = [[processList objectAtIndex:i] objectForKey:@"NSApplicationProcessIdentifier"]; + name = [[processList objectAtIndex:i] objectForKey:@"NSApplicationName"]; + + // PID NAME + length += sizeof(u_int32_t) + [name length] + 1; + } + + header.size = length; + length += sizeof(header); + // HEADER + + if ( (buffer = (char *)malloc( length ))==NULL ) + { + NSLog( @"sendProcessList failed" ); + return; + } + + ptr = buffer; + + COPY_TO_BUFFER( ptr, &header, sizeof(header) ); + COPY_TO_BUFFER( ptr, &processCount, sizeof(processCount) ); + + for ( i = 0; i < max; i++ ) + { + pidNum = [[[processList objectAtIndex:i] objectForKey:@"NSApplicationProcessIdentifier"] unsignedLongValue]; + name = [[processList objectAtIndex:i] objectForKey:@"NSApplicationName"]; + + COPY_TO_BUFFER( ptr, &pidNum, sizeof(pid) ); + COPY_TO_BUFFER( ptr, [name lossyCString], [name length] + 1 ); + } + + lengthAfter = length; + + if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length ) + { + NSLog( @"sendProcessList failed" ); + } + + free( buffer ); +} + + +- (void)sendSearchFinished +{ + PacketHeader header; + int length = sizeof(header); + + header.checksum = RandomChecksum(); + header.function = 6; + header.size = 0; + + if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) ) + { + NSLog( @"sendSearchFinished failed" ); + } +} + +- (void)sendVariableList:(TCaddress const *)data amount:(int)amount +{ + PacketHeader header; + int length; + int lengthAfter; + + char *buffer, *ptr; + + header.checksum = RandomChecksum(); + header.function = 7; + header.size = sizeof(amount) + TCAddressSize*amount; + // AMOUNT DATA + + lengthAfter = length = header.size + sizeof(header); + + if ( (buffer = (char *)malloc( length )) == NULL ) + { + NSLog( @"sendVariableList:amount: failed" ); + return; + } + + ptr = buffer; + + COPY_TO_BUFFER( ptr, &header, sizeof(header) ); + COPY_TO_BUFFER( ptr, &amount, sizeof(amount) ); + COPY_TO_BUFFER( ptr, data, TCAddressSize*amount ); + + if ( SendBuffer( sockfd, buffer, &length ) == -1 || lengthAfter != length ) + { + NSLog( @"sendVariableList:amount: failed" ); + } + + free( buffer ); +} + +- (void)sendChangeFinished +{ + PacketHeader header; + int length = sizeof(header); + + header.checksum = RandomChecksum(); + header.function = 9; + header.size = 0; + + if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) ) + { + NSLog( @"sendChangeFinished failed" ); + } +} + +- (void)sendError:(NSString *)msg fatal:(BOOL)fatal +{ + PacketHeader header; + int length; + int lengthAfter; + + u_int32_t type = (fatal)? 1:0; + + char *buffer, *ptr; + + header.checksum = RandomChecksum(); + header.function = 11; + header.size = sizeof(type) + [msg length] + 1; + // FATAL STRING + + lengthAfter = length = header.size + sizeof(header); + + if ( (buffer = (char *)malloc( length )) == NULL ) + { + NSLog( @"sendError:fatal: failed" ); + return; + } + + ptr = buffer; + + COPY_TO_BUFFER( ptr, &header, sizeof(header) ); + COPY_TO_BUFFER( ptr, &type, sizeof(type) ); + COPY_TO_BUFFER( ptr, [msg lossyCString], [msg length] + 1 ); + + if ( SendBuffer( sockfd, buffer, &length ) == -1 || lengthAfter != length ) + { + NSLog( @"sendError:fatal: failed" ); + } + + free( buffer ); +} + +- (void)sendVariableValue:(u_int32_t)index +{ + +} + +- (void)sendUndoFinished +{ + PacketHeader header; + int length = sizeof(header); + + header.checksum = RandomChecksum(); + header.function = 15; + header.size = 0; + + if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) ) + { + NSLog( @"sendUndoFinished failed" ); + } +} + +- (void)sendRedoFinished +{ + PacketHeader header; + int length = sizeof(header); + + header.checksum = RandomChecksum(); + header.function = 17; + header.size = 0; + + if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) ) + { + NSLog( @"sendRedoFinished failed" ); + } +} + +- (void)sendUndoRedoStatus +{ + PacketHeader header; + int length; + int lengthAfter; + + u_int32_t undoCount = (u_int32_t)[searchResults count]; + u_int32_t redoCount = (u_int32_t)[searchResultsUndone count]; + + char *buffer, *ptr; + + header.checksum = RandomChecksum(); + header.function = 19; + header.size = 2 * sizeof(u_int32_t); + + length = lengthAfter = sizeof(header) + header.size; + + if ( (buffer = (char *)malloc( length )) == NULL ) + { + NSLog( @"sendSetTargetPID: failed" ); + } + + ptr = buffer; + + COPY_TO_BUFFER( ptr, &header, sizeof(header) ); + COPY_TO_BUFFER( ptr, &undoCount, sizeof(undoCount) ); + COPY_TO_BUFFER( ptr, &redoCount, sizeof(redoCount) ); + + if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length ) + { + NSLog( @"sendUndoRedoStatus: failed" ); + } + + free( buffer ); +} + +- (void)sendAppLaunched:(NSDictionary *)appInfo +{ + PacketHeader header; + + char *buffer, *ptr; + + int length = 0; + int lengthAfter; + + u_int32_t pid = [[appInfo objectForKey:@"NSApplicationProcessIdentifier"] unsignedLongValue]; + NSString *name = [appInfo objectForKey:@"NSApplicationName"]; + + // PID NAME + length += sizeof(u_int32_t) + [name length] + 1; + + header.checksum = RandomChecksum(); + header.function = 21; + header.size = length; + + length += sizeof(header); + // HEADER + + if ( (buffer = (char *)malloc( length ))==NULL ) + { + NSLog( @"sendAppLaunched: failed" ); + + return; + } + + ptr = buffer; + + COPY_TO_BUFFER( ptr, &header, sizeof(header) ); + COPY_TO_BUFFER( ptr, &pid, sizeof(pid) ); + COPY_TO_BUFFER( ptr, [name lossyCString], [name length] + 1 ); + + lengthAfter = length; + + if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length ) + { + NSLog( @"sendAppLaunched: failed" ); + } + + free( buffer ); +} + + +- (void)sendAppQuit:(NSDictionary *)appInfo +{ + PacketHeader header; + + char *buffer, *ptr; + + int length = 0; + int lengthAfter; + + u_int32_t pid = [[appInfo objectForKey:@"NSApplicationProcessIdentifier"] unsignedLongValue]; + + // PID + length += sizeof(pid); + + header.checksum = RandomChecksum(); + header.function = 22; + header.size = length; + + length += sizeof(header); + // HEADER + + if ( (buffer = (char *)malloc( length ))==NULL ) + { + NSLog( @"sendAppQuit: failed" ); + + return; + } + + ptr = buffer; + + COPY_TO_BUFFER( ptr, &header, sizeof(header) ); + COPY_TO_BUFFER( ptr, &pid, sizeof(pid) ); + + lengthAfter = length; + + if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length ) + { + NSLog( @"sendAppQuit: failed" ); + } + + free( buffer ); +} + +- (void)sendTargetAppQuit +{ + PacketHeader header; + int length = sizeof(header); + + header.checksum = RandomChecksum(); + header.function = 23; + header.size = 0; + + if ( SendBuffer( sockfd, (char *)(&header), &length ) == -1 || length != sizeof(header) ) + { + NSLog( @"sendTargetAppQuit failed" ); + } +} + +- (void)sendPauseFinished:(BOOL)paused +{ + PacketHeader header; + + char *buffer, *ptr; + + // PAUSED + int length = sizeof(paused); + int lengthAfter; + + header.checksum = RandomChecksum(); + header.function = 24; + header.size = length; + + length += sizeof(header); + // HEADER + + if ( (buffer = (char *)malloc( length ))==NULL ) + { + NSLog( @"sendPauseFinished: failed" ); + + return; + } + + ptr = buffer; + + COPY_TO_BUFFER( ptr, &header, sizeof(header) ); + COPY_TO_BUFFER( ptr, &paused, sizeof(paused) ); + + lengthAfter = length; + + if ( SendBuffer( sockfd, buffer, &lengthAfter ) == -1 || lengthAfter != length ) + { + NSLog( @"sendPauseFinished: failed" ); + } + + free( buffer ); +} + + +- (void)handleClearSearch +{ + [searchResults removeAllObjects]; + [searchResultsUndone removeAllObjects]; + + [self unpause]; +} + +- (void)handleSearch:(char const *)data size:(int)dataSize +{ + TCtype type; + TCsize size; + + char *ptr = (char *)data; + + [self setAction:@"Searching"]; + + COPY_FROM_BUFFER( &type, ptr, sizeof(type) ); + COPY_FROM_BUFFER( &size, ptr, sizeof(size) ); + + if ( ![searchResults lastObject] ) + { + switch ( type ) + { + case TYPE_STRING: + { + switch ( size ) + { + case SIZE_8_BIT: + { + [self firstSearchString8bit:ptr size:(dataSize - (ptr - data))]; + } + break; + } + } + break; + + case TYPE_INTEGER: + { + switch ( size ) + { + case SIZE_8_BIT: + { + int8_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self firstSearchIntegerChar:value]; + } + break; + + case SIZE_16_BIT: + { + int16_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self firstSearchIntegerShort:value]; + } + break; + + case SIZE_32_BIT: + { + int32_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self firstSearchIntegerLong:value]; + } + break; + } + } + break; + + case TYPE_DECIMAL: + { + switch ( size ) + { + case SIZE_32_BIT: + { + float value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self firstSearchDecimalFloat:value]; + } + break; + + case SIZE_64_BIT: + { + double value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self firstSearchDecimalDouble:value]; + } + break; + } + } + break; + } + } + else + { + switch ( type ) + { + case TYPE_STRING: + { + switch ( size ) + { + case SIZE_8_BIT: + { + [self searchString8bit:ptr size:(dataSize - (ptr - data))]; + + break; + } + } + } + break; + + case TYPE_INTEGER: + { + switch ( size ) + { + case SIZE_8_BIT: + { + int8_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self searchIntegerChar:value]; + + break; + } + + case SIZE_16_BIT: + { + int16_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self searchIntegerShort:value]; + + break; + } + + case SIZE_32_BIT: + { + int32_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self searchIntegerLong:value]; + + break; + } + } + } + break; + + case TYPE_DECIMAL: + { + switch ( size ) + { + case SIZE_32_BIT: + { + float value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self searchDecimalFloat:value]; + } + break; + + case SIZE_64_BIT: + { + double value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self searchDecimalDouble:value]; + } + break; + } + } + break; + } + } + + [self sendVariableList:[(SearchResults *)[searchResults lastObject] data] amount:[[searchResults lastObject] amount]]; + [self sendSearchFinished]; + [self sendUndoRedoStatus]; + + [self setAction:nil]; +} + +- (void)handleChange:(char const *)data size:(int)dataSize +{ + TCtype type; + TCsize size; + + TCaddress *addresses = NULL; + int count; + + char *ptr = (char *)data; + + [self setAction:@"Changing"]; + + // read out the type and size of the variable. + COPY_FROM_BUFFER( &type, ptr, sizeof(type) ); + COPY_FROM_BUFFER( &size, ptr, sizeof(size) ); + + // read the amount of addresses. + COPY_FROM_BUFFER( &count, ptr, sizeof(count) ); + + // save the pointer to the addresses. + addresses = (TCaddress *)ptr; + ptr += TCAddressSize*count; + + switch ( type ) + { + case TYPE_STRING: + { + switch ( size ) + { + case SIZE_8_BIT: + { + [self changeString8bit:ptr size:(dataSize - (ptr - data)) addresses:addresses count:count]; + } + break; + } + } + break; + + case TYPE_INTEGER: + { + switch ( size ) + { + case SIZE_8_BIT: + { + int8_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self changeIntegerChar:value addresses:addresses count:count]; + } + break; + + case SIZE_16_BIT: + { + int16_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self changeIntegerShort:value addresses:addresses count:count]; + } + break; + + case SIZE_32_BIT: + { + int32_t value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self changeIntegerLong:value addresses:addresses count:count]; + } + break; + } + } + break; + + case TYPE_DECIMAL: + { + switch ( size ) + { + case SIZE_32_BIT: + { + float value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self changeDecimalFloat:value addresses:addresses count:count]; + } + break; + + case SIZE_64_BIT: + { + double value; + + COPY_FROM_BUFFER( &value, ptr, sizeof(value) ); + [self changeDecimalDouble:value addresses:addresses count:count]; + } + break; + } + } + break; + } + + [self sendChangeFinished]; + + [self setAction:nil]; +} + +- (void)handlePauseTarget +{ + if ( !processPaused ) + { + int wait_status; + + if ( ptrace( PT_ATTACH, processID, 0, 0 ) != -1 ) + { + if ( waitpid( processID, &wait_status, WUNTRACED ) == processID ) + { + if ( WIFSTOPPED(wait_status) ) + { + processPaused = YES; + [self sendPauseFinished:YES]; + } + else + { + NSLog( @"ERROR: process couldn't be paused" ); + [self sendPauseFinished:NO]; + [self sendError:@"Process couldn't be paused." fatal:NO]; + } + } + else + { + NSLog( @"ERROR: process couldn't be paused" ); + [self sendPauseFinished:NO]; + [self sendError:@"Process couldn't be paused." fatal:NO]; + } + } + else + { + NSLog( @"ERROR: process couldn't be paused" ); + [self sendPauseFinished:NO]; + [self sendError:@"Process couldn't be paused." fatal:NO]; + } + } + else + { + ptrace( PT_DETACH, processID, 0, 0 ); + + processPaused = NO; + [self sendPauseFinished:NO]; + } +} + +- (void)handleUndo +{ + SearchResults *results = [searchResults lastObject]; + + if ( results ) + { + [searchResultsUndone addObject:results]; + [searchResults removeLastObject]; + } + + results = [searchResults lastObject]; + if ( results ) + { + [self sendVariableList:[results data] amount:[results amount]]; + } + else + { + [self sendVariableList:NULL amount:0]; + } + + [self sendUndoFinished]; + [self sendUndoRedoStatus]; +} + +- (void)handleRedo +{ + SearchResults *results = [searchResultsUndone lastObject]; + + if ( results ) + { + [searchResults addObject:results]; + [searchResultsUndone removeLastObject]; + } + + results = [searchResults lastObject]; + if ( results ) + { + [self sendVariableList:[results data] amount:[results amount]]; + } + else + { + [self sendVariableList:NULL amount:0]; + } + + [self sendRedoFinished]; + [self sendUndoRedoStatus]; +} + +- (void)handleSetTargetPID:(char const *)data size:(int)size +{ + char *ptr = (char *)data; + + pid_t pid; + + COPY_FROM_BUFFER( &pid, ptr, sizeof(pid) ); + + [self setPID:pid]; +} + + +- (void)unpause +{ + if ( processPaused ) + { + [self handlePauseTarget]; + } +} + +- (void)setPID:(pid_t)pid +{ + kern_return_t result; + + [self unpause]; + + processID = pid; + + if ( (result = task_for_pid( current_task(), processID, &processTask)) != KERN_SUCCESS ) + { + NSLog( @"task_for_pid returned error: %i", result ); + } +} + + +- (void)dealloc +{ + [self unpause]; + + [[[NSWorkspace sharedWorkspace] notificationCenter] removeObserver:self]; + + [searchResults release]; + [searchResultsUndone release]; + + [super dealloc]; +} + + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%% NSWorkspaceDidLaunchApplicationNotification Notification +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +- (void)processListChanged:(NSNotification *)note +{ + pid_t pid = [[[note userInfo] objectForKey:@"NSApplicationProcessIdentifier"] intValue]; + + if ( /*pid != getpid()*/ sockfd != -1 ) + { + if ( [[note name] isEqualToString:@"NSWorkspaceDidLaunchApplicationNotification"] ) + { + [self sendAppLaunched:[note userInfo]]; + } + else + { + [self sendAppQuit:[note userInfo]]; + + if ( pid == processID ) + { + [self sendTargetAppQuit]; + + // we can't set the new target here because this method is not called + // in the server thread. the client will have to change it. + //[self setPID:[rootProxy serverFirstProcess]]; + processPaused = NO; + } + } + } +} + + +@end + + +/*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%% +%%%%%%%%%%%%%%%%%%%%%% Internal Functions +%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/ + + +BOOL compare_float( float a, float b ) +{ + float const feps = 0.0001f; + + return feps > fabsf( a - b ); +} + +BOOL compare_double( double a, double b ) +{ + double const deps = 0.0000001; + + return deps > fabs( a - b ); +} \ No newline at end of file