2 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
6 // Created: Sun Sep 07 2003
8 // Copyright: 2003 Chaz McGarvey. All rights reserved.
9 // ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
11 #import "CheatServer.h"
13 #import "SearchResults.h"
23 //BOOL inline compare_float( float a, float b );
24 //BOOL inline compare_double( double a, double b );
27 @implementation CheatServer
30 + (NSConnection
*)serverWithDelegate
:(id)delegate socket
:(int)sock
32 NSPort
*rPort
= [NSPort port
], *sPort
= [NSPort port
];
33 NSConnection
*connection
;
36 connection
= [[NSConnection alloc
] initWithReceivePort
:rPort sendPort
:sPort
];
37 [connection setRootObject
:delegate
];
39 array
= [NSArray arrayWithObjects
:sPort
, rPort
, [NSNumber numberWithInt
:sock
], nil];
40 [NSThread detachNewThreadSelector
:@selector(serverThread
:) toTarget
:self withObject
:array
];
42 return [connection autorelease
];
45 + (void)serverThread
:(NSArray
*)array
47 NSAutoreleasePool
*pool
= [[NSAutoreleasePool alloc
] init
];
48 NSConnection
*connection
= [NSConnection connectionWithReceivePort
:[array objectAtIndex
:0] sendPort
:[array objectAtIndex
:1]];
49 CheatServer
*object
= [[self alloc
] initWithRootProxy
:[connection rootProxy
]];
51 [object handleSocket
:[[array objectAtIndex
:2] intValue
]];
59 - (id)initWithRootProxy
:(id)proxy
61 if ( self = [super init
] )
63 NSNotificationCenter
*nc
= [[NSWorkspace sharedWorkspace
] notificationCenter
];
67 [nc addObserver
:self selector
:@selector(processListChanged
:) name
:@
"NSWorkspaceDidLaunchApplicationNotification" object
:nil];
68 [nc addObserver
:self selector
:@selector(processListChanged
:) name
:@
"NSWorkspaceDidTerminateApplicationNotification" object
:nil];
70 [self setPID
:[rootProxy serverFirstProcess
]];
74 searchResults
= [[NSMutableArray alloc
] init
];
75 searchResultsUndone
= [[NSMutableArray alloc
] init
];
82 - (void)handleSocket
:(int)sock
84 struct sockaddr identifier
;
85 int addrLen
= sizeof(identifier
);
92 if ( getpeername( sockfd
, &identifier
, &addrLen
) == -1 )
94 NSLog( @
"ERROR: getpeername() failed" );
97 if ( identifier.sa_family
== AF_INET
)
99 struct sockaddr_in addr
;
101 addrLen
= sizeof(addr
);
103 if ( getpeername( sockfd
, (struct sockaddr
*)(&addr
), &addrLen
) == -1 )
105 NSLog( @
"ERROR: getpeername() failed" );
108 if ( (addressCString
= inet_ntoa( addr.sin_addr
)) == NULL
)
110 NSLog( @
"ERROR: inet_ntoa() failed" );
113 address
= [NSString stringWithCString
:addressCString
];
117 struct sockaddr_un addr
;
119 addrLen
= sizeof(addr
);
121 if ( getpeername( sockfd
, (struct sockaddr
*)(&addr
), &addrLen
) == -1 )
123 NSLog( @
"ERROR: getpeername() failed" );
126 NSLog( @
"client connection: %s", addr.sun_path
);
128 address
= [NSString stringWithString
:@
"127.0.0.1"];
131 [rootProxy server
:self connectedWithSocket
:sockfd
];
133 [self setAddress
:address
];
134 [self setAction
:nil];
140 fd_set fdset
, master
;
153 FD_SET( sockfd
, &master
);
157 NSLog( @
"SERVER start" );
163 select( numfds
, &fdset
, NULL
, NULL
, &tv
);
165 if ( FD_ISSET( sockfd
, &fdset
) )
167 if ( (result
= ReadBuffer( sockfd
, (char *)(&header
), sizeof(header
) )) != sizeof(header
) )
172 if ( !VerifyChecksum( header.checksum
) )
174 NSLog( @
"checksum failed" );
177 if ( header.size
!= 0 )
179 if ( (data
= (char *)malloc( header.size
)) == NULL
)
181 NSLog( @
"failed to allocate buffer for reading a network packet" );
185 if ( (result
= ReadBuffer( sockfd
, data
, header.size
)) != header.size
)
187 NSLog( @
"failed to read the data of a network packet" );
193 //NSLog( @"SERVER message %i/%i/%i", header.checksum, header.function, header.size );
195 switch ( header.function
)
198 [self sendProcessList
];
202 [self handleClearSearch
];
206 [self handleSearch
:data size
:header.size
];
210 [self handleChange
:data size
:header.size
];
214 [self handlePauseTarget
];
226 [self handleSetTargetPID
:data size
:header.size
];
231 if ( header.size
!= 0 )
240 NSLog( @
"SERVER close" );
242 [rootProxy serverDisconnected
:self];
246 - (void)setAddress
:(NSString
*)address
248 [rootProxy server
:self changedAddress
:address
];
251 - (void)setAction
:(NSString
*)action
255 [rootProxy server
:self changedAction
:@
"Idle"];
259 [rootProxy server
:self changedAction
:action
];
263 - (void)firstSearchString8bit
:(char const *)value size
:(int)vsize
265 kern_return_t result
;
267 vm_address_t address
= 0x0;
269 vm_region_basic_info_data_t info
;
270 mach_msg_type_number_t infoCnt
= 8;
271 mach_port_t object_name
= 0;
274 vm_size_t dataLength
;
276 TCaddress
*results
= NULL
;
277 int resultsAmount
= 0;
279 NSLog( @
"string search: %s", value
);
283 if ( (result
= vm_region( processTask
, &address
, &size
, VM_REGION_BASIC_INFO
, (vm_region_info_t
)(&info
), &infoCnt
, &object_name
)) != KERN_SUCCESS
)
285 if ( result
!= KERN_INVALID_ADDRESS
)
287 NSLog( @
"vm_region returned error: %i", result
);
292 if ( (info.protection
& VM_PROT_READ
) && (info.protection
& VM_PROT_WRITE
))
294 data
= (char *)malloc( size
);
297 if ( (result
= vm_read_overwrite( processTask
, address
, size
, (vm_address_t
)data
, &dataLength
)) != KERN_SUCCESS
&& result
!= KERN_PROTECTION_FAILURE
)
299 NSLog( @
"vm_read_overwrite returned error: %i", result
);
304 if ( result
== KERN_SUCCESS
)
306 int i
, top
= dataLength
- vsize
;
308 if ( (results
= realloc( results
, TCAddressSize
*resultsAmount
+ dataLength
)) == NULL
)
310 NSLog( @
"ERROR: could not expand buffer" );
314 for ( i
= 0; i
< top
; i
++ )
316 if ( strncmp( value
, data
+i
, vsize
) == 0 )
318 results
[resultsAmount
++] = (TCaddress
)address
+ i
;
329 realloc( results
, TCAddressSize
*resultsAmount
);
330 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_8_BIT data
:results amount
:resultsAmount
]];
332 NSLog( @
"found %i of %i", resultsAmount
, value
);
335 - (void)firstSearchIntegerChar
:(int8_t
)value
337 kern_return_t result
;
339 vm_address_t address
= 0x0;
341 vm_region_basic_info_data_t info
;
342 mach_msg_type_number_t infoCnt
= 8;
343 mach_port_t object_name
= 0;
346 vm_size_t dataLength
;
348 TCaddress
*results
= NULL
;
349 int resultsAmount
= 0;
353 if ( (result
= vm_region( processTask
, &address
, &size
, VM_REGION_BASIC_INFO
, (vm_region_info_t
)(&info
), &infoCnt
, &object_name
)) != KERN_SUCCESS
)
355 if ( result
!= KERN_INVALID_ADDRESS
)
357 NSLog( @
"vm_region returned error: %i", result
);
362 if ( (info.protection
& VM_PROT_READ
) && (info.protection
& VM_PROT_WRITE
))
364 data
= (int8_t
*)malloc( size
);
367 if ( (result
= vm_read_overwrite( processTask
, address
, size
, (vm_address_t
)data
, &dataLength
)) != KERN_SUCCESS
&& result
!= KERN_PROTECTION_FAILURE
)
369 NSLog( @
"vm_read_overwrite returned error: %i", result
);
374 if ( result
== KERN_SUCCESS
)
378 if ( (results
= (TCaddress
*)realloc( results
, TCAddressSize
*resultsAmount
+ TCAddressSize
*dataLength
)) == NULL
)
380 NSLog( @
"ERROR: could not expand buffer" );
384 for ( i
= 0; i
< dataLength
; i
++ )
386 if ( *(data
+i
) == value
)
388 results
[resultsAmount
++] = (TCaddress
)address
+ i
;
399 realloc( results
, TCAddressSize
*resultsAmount
);
400 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_8_BIT data
:results amount
:resultsAmount
]];
402 NSLog( @
"found %i of %i", resultsAmount
, value
);
405 - (void)firstSearchIntegerShort
:(int16_t
)value
407 kern_return_t result
;
409 vm_address_t address
= 0x0;
411 vm_region_basic_info_data_t info
;
412 mach_msg_type_number_t infoCnt
= 8;
413 mach_port_t object_name
= 0;
416 vm_size_t dataLength
;
418 TCaddress
*results
= NULL
;
419 int resultsAmount
= 0;
423 if ( (result
= vm_region( processTask
, &address
, &size
, VM_REGION_BASIC_INFO
, (vm_region_info_t
)(&info
), &infoCnt
, &object_name
)) != KERN_SUCCESS
)
425 if ( result
!= KERN_INVALID_ADDRESS
)
427 NSLog( @
"vm_region returned error: %i", result
);
432 if ( (info.protection
& VM_PROT_READ
) && (info.protection
& VM_PROT_WRITE
))
434 data
= (int16_t
*)malloc( size
);
437 if ( (result
= vm_read_overwrite( processTask
, address
, size
, (vm_address_t
)data
, &dataLength
)) != KERN_SUCCESS
&& result
!= KERN_PROTECTION_FAILURE
)
439 NSLog( @
"vm_read_overwrite returned error: %i", result
);
444 if ( result
== KERN_SUCCESS
)
446 int i
, top
= dataLength
/ sizeof(value
);
448 if ( (results
= (TCaddress
*)realloc( results
, TCAddressSize
*resultsAmount
+ 2*dataLength
)) == NULL
)
450 NSLog( @
"ERROR: could not expand buffer" );
454 for ( i
= 0; i
< top
; i
++ )
456 if ( *(data
+i
) == value
)
458 results
[resultsAmount
++] = (TCaddress
)address
+ i
* sizeof(value
);
469 realloc( results
, TCAddressSize
*resultsAmount
);
470 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_16_BIT data
:results amount
:resultsAmount
]];
472 NSLog( @
"found %i of %i", resultsAmount
, value
);
475 - (void)firstSearchIntegerLong
:(int32_t
)value
477 kern_return_t result
;
479 vm_address_t address
= 0x0;
481 vm_region_basic_info_data_t info
;
482 mach_msg_type_number_t infoCnt
= 8;
483 mach_port_t object_name
= 0;
486 vm_size_t dataLength
;
488 TCaddress
*results
= NULL
;
489 int resultsAmount
= 0;
491 /*unsigned zone_count = 10;
492 vm_address_t *zones = (vm_address_t *)malloc( zone_count * sizeof(vm_address_t) );
493 //memory_reader_t reader;
495 if ( (result = malloc_get_all_zones( processTask, NULL, &zones, &zone_count )) != KERN_SUCCESS )
497 NSLog( @"malloc_get_all_zones error: %i", result );
501 //address = zones[0];
505 for ( i = 0; i < 10; i++ )
507 NSLog( @"malloc_get_all_zones[%i] = %X", i, (vm_address_t)zones[i] );
513 if ( (result
= vm_region( processTask
, &address
, &size
, VM_REGION_BASIC_INFO
, (vm_region_info_t
)(&info
), &infoCnt
, &object_name
)) != KERN_SUCCESS
)
515 if ( result
!= KERN_INVALID_ADDRESS
)
517 NSLog( @
"vm_region returned error: %i", result
);
522 if ( (info.protection
& VM_PROT_READ
) && (info.protection
& VM_PROT_WRITE
) )
524 data
= (int32_t
*)malloc( size
);
527 NSLog( @
"address: %.8X size: %i", address
, size
);
529 if ( (result
= vm_read_overwrite( processTask
, address
, size
, (vm_address_t
)data
, &dataLength
)) != KERN_SUCCESS
&& result
!= KERN_PROTECTION_FAILURE
)
531 NSLog( @
"vm_read_overwrite returned error: %i", result
);
536 if ( result
== KERN_SUCCESS
)
538 int i
, top
= dataLength
/ sizeof(value
);
540 if ( (results
= (TCaddress
*)realloc( results
, TCAddressSize
*resultsAmount
+ dataLength
)) == NULL
)
542 NSLog( @
"ERROR: could not expand buffer" );
546 for ( i
= 0; i
< top
; i
++ )
548 if ( *(data
+i
) == value
)
550 results
[resultsAmount
++] = (TCaddress
)address
+ i
* sizeof(value
);
561 realloc( results
, TCAddressSize
*resultsAmount
);
562 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_32_BIT data
:results amount
:resultsAmount
]];
564 NSLog( @
"found %i of %i", resultsAmount
, value
);
568 - (void)firstSearchDecimalFloat
:(float)value
570 kern_return_t result
;
572 vm_address_t address
= 0x0;
574 vm_region_basic_info_data_t info
;
575 mach_msg_type_number_t infoCnt
= 8;
576 mach_port_t object_name
= 0;
579 vm_size_t dataLength
;
581 TCaddress
*results
= NULL
;
582 int resultsAmount
= 0;
586 if ( (result
= vm_region( processTask
, &address
, &size
, VM_REGION_BASIC_INFO
, (vm_region_info_t
)(&info
), &infoCnt
, &object_name
)) != KERN_SUCCESS
)
588 if ( result
!= KERN_INVALID_ADDRESS
)
590 NSLog( @
"vm_region returned error: %i", result
);
595 if ( (info.protection
& VM_PROT_READ
) && (info.protection
& VM_PROT_WRITE
))
597 data
= (float *)malloc( size
);
600 if ( (result
= vm_read_overwrite( processTask
, address
, size
, (vm_address_t
)data
, &dataLength
)) != KERN_SUCCESS
&& result
!= KERN_PROTECTION_FAILURE
)
602 NSLog( @
"vm_read_overwrite returned error: %i", result
);
607 if ( result
== KERN_SUCCESS
)
609 int i
, top
= dataLength
/ sizeof(value
);
611 if ( (results
= realloc( results
, TCAddressSize
*resultsAmount
+ dataLength
)) == NULL
)
613 NSLog( @
"ERROR: could not expand buffer" );
617 for ( i
= 0; i
< top
; i
++ )
619 if ( cl_compare_float_eps( *(data
+i
), value
, 0.1f
) == 0 )
621 results
[resultsAmount
++] = (TCaddress
)address
+ i
* sizeof(value
);
632 realloc( results
, TCAddressSize
*resultsAmount
);
633 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_DECIMAL size
:SIZE_32_BIT data
:results amount
:resultsAmount
]];
635 NSLog( @
"found %i of %i", resultsAmount
, value
);
638 - (void)firstSearchDecimalDouble
:(double)value
640 kern_return_t result
;
642 vm_address_t address
= 0x0;
644 vm_region_basic_info_data_t info
;
645 mach_msg_type_number_t infoCnt
= 8;
646 mach_port_t object_name
= 0;
649 vm_size_t dataLength
;
651 TCaddress
*results
= NULL
;
652 int resultsAmount
= 0;
654 NSLog( @
"float search" );
658 if ( (result
= vm_region( processTask
, &address
, &size
, VM_REGION_BASIC_INFO
, (vm_region_info_t
)(&info
), &infoCnt
, &object_name
)) != KERN_SUCCESS
)
660 if ( result
!= KERN_INVALID_ADDRESS
)
662 NSLog( @
"vm_region returned error: %i", result
);
667 if ( (info.protection
& VM_PROT_READ
) && (info.protection
& VM_PROT_WRITE
))
669 data
= (double *)malloc( size
);
672 if ( (result
= vm_read_overwrite( processTask
, address
, size
, (vm_address_t
)data
, &dataLength
)) != KERN_SUCCESS
&& result
!= KERN_PROTECTION_FAILURE
)
674 NSLog( @
"vm_read_overwrite returned error: %i", result
);
679 if ( result
== KERN_SUCCESS
)
681 int i
, top
= dataLength
/ sizeof(value
);
683 if ( (results
= realloc( results
, TCAddressSize
*resultsAmount
+ dataLength
)) == NULL
)
685 NSLog( @
"ERROR: could not expand buffer" );
689 for ( i
= 0; i
< top
; i
++ )
691 if ( cl_compare_double_eps( *(data
+i
), value
, 0.1 ) == 0 )
693 results
[resultsAmount
++] = (TCaddress
)address
+ i
* sizeof(value
);
704 realloc( results
, TCAddressSize
*resultsAmount
);
705 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_DECIMAL size
:SIZE_64_BIT data
:results amount
:resultsAmount
]];
707 NSLog( @
"found %i of %i", resultsAmount
, value
);
711 - (void)searchString8bit
:(char const *)value size
:(int)vsize
713 kern_return_t result
;
716 vm_size_t dataLength
;
719 int resultsAmount
= 0;
721 SearchResults
*lastResults
= [searchResults lastObject
];
722 TCaddress
*lastResultsData
= [lastResults data
];
723 int i
, lastResultsAmount
= [lastResults amount
];
725 if ( [lastResults type
] != TYPE_INTEGER ||
[lastResults size
] != SIZE_8_BIT
)
727 [self sendError
:@
"This search is incompatible with the previous search." fatal
:NO
];
731 if ( (results
= (TCaddress
*)malloc( TCAddressSize
*lastResultsAmount
)) == NULL
)
733 NSLog( @
"ERROR: could not create buffer" );
735 [self sendError
:@
"The server cancelled the search because it ran out of memory." fatal
:NO
];
739 for ( i
= 0; i
< lastResultsAmount
; i
++ )
741 TCaddress address
= lastResultsData
[i
];
743 dataLength
= sizeof(data
);
745 if ( (result
= vm_read_overwrite( processTask
, address
, sizeof(data
), (vm_address_t
)(&data
), &dataLength
)) == KERN_SUCCESS
)
747 if ( data
== value
[0] )
749 results
[resultsAmount
++] = address
;
754 if ( result
!= KERN_PROTECTION_FAILURE
)
756 NSLog( @
"vm_read_overwrite returned error: %i", result
);
762 realloc( results
, TCAddressSize
*resultsAmount
);
763 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_8_BIT data
:results amount
:resultsAmount
]];
765 NSLog( @
"found %i of %i", resultsAmount
, value
);
768 - (void)searchIntegerChar
:(int8_t
)value
770 kern_return_t result
;
773 vm_size_t dataLength
;
776 int resultsAmount
= 0;
778 SearchResults
*lastResults
= [searchResults lastObject
];
779 TCaddress
*lastResultsData
= [lastResults data
];
780 int i
, lastResultsAmount
= [lastResults amount
];
782 if ( [lastResults type
] != TYPE_INTEGER ||
[lastResults size
] != SIZE_8_BIT
)
784 [self sendError
:@
"This search is incompatible with the previous search." fatal
:NO
];
788 if ( (results
= (TCaddress
*)malloc( TCAddressSize
*lastResultsAmount
)) == NULL
)
790 NSLog( @
"ERROR: could not create buffer" );
792 [self sendError
:@
"The server cancelled the search because it ran out of memory." fatal
:NO
];
796 for ( i
= 0; i
< lastResultsAmount
; i
++ )
798 TCaddress address
= lastResultsData
[i
];
800 dataLength
= sizeof(data
);
802 if ( (result
= vm_read_overwrite( processTask
, address
, sizeof(data
), (vm_address_t
)(&data
), &dataLength
)) == KERN_SUCCESS
)
806 results
[resultsAmount
++] = address
;
811 if ( result
!= KERN_PROTECTION_FAILURE
)
813 NSLog( @
"vm_read_overwrite returned error: %i", result
);
819 realloc( results
, TCAddressSize
*resultsAmount
);
820 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_8_BIT data
:results amount
:resultsAmount
]];
822 NSLog( @
"found %i of %i", resultsAmount
, value
);
825 - (void)searchIntegerShort
:(int16_t
)value
827 kern_return_t result
;
830 vm_size_t dataLength
;
833 int resultsAmount
= 0;
835 SearchResults
*lastResults
= [searchResults lastObject
];
836 TCaddress
*lastResultsData
= [lastResults data
];
837 int i
, lastResultsAmount
= [lastResults amount
];
839 if ( [lastResults type
] != TYPE_INTEGER ||
[lastResults size
] != SIZE_16_BIT
)
841 [self sendError
:@
"This search is incompatible with the previous search." fatal
:NO
];
845 if ( (results
= (TCaddress
*)malloc( TCAddressSize
*lastResultsAmount
)) == NULL
)
847 NSLog( @
"ERROR: could not create buffer" );
849 [self sendError
:@
"The server cancelled the search because it ran out of memory." fatal
:NO
];
853 for ( i
= 0; i
< lastResultsAmount
; i
++ )
855 TCaddress address
= lastResultsData
[i
];
857 dataLength
= sizeof(data
);
859 if ( (result
= vm_read_overwrite( processTask
, address
, sizeof(data
), (vm_address_t
)(&data
), &dataLength
)) == KERN_SUCCESS
)
863 results
[resultsAmount
++] = address
;
868 if ( result
!= KERN_PROTECTION_FAILURE
)
870 NSLog( @
"vm_read_overwrite returned error: %i", result
);
876 realloc( results
, TCAddressSize
*resultsAmount
);
877 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_16_BIT data
:results amount
:resultsAmount
]];
879 NSLog( @
"found %i of %i", resultsAmount
, value
);
882 - (void)searchIntegerLong
:(int32_t
)value
884 kern_return_t result
;
887 vm_size_t dataLength
;
890 int resultsAmount
= 0;
892 SearchResults
*lastResults
= [searchResults lastObject
];
893 TCaddress
*lastResultsData
= [lastResults data
];
894 int i
, lastResultsAmount
= [lastResults amount
];
896 if ( [lastResults type
] != TYPE_INTEGER ||
[lastResults size
] != SIZE_32_BIT
)
898 [self sendError
:@
"This search is incompatible with the previous search." fatal
:NO
];
902 if ( (results
= (TCaddress
*)malloc( TCAddressSize
*lastResultsAmount
)) == NULL
)
904 NSLog( @
"ERROR: could not create buffer" );
906 [self sendError
:@
"The server cancelled the search because it ran out of memory." fatal
:NO
];
910 for ( i
= 0; i
< lastResultsAmount
; i
++ )
912 TCaddress address
= lastResultsData
[i
];
914 dataLength
= sizeof(data
);
916 if ( (result
= vm_read_overwrite( processTask
, address
, sizeof(data
), (vm_address_t
)(&data
), &dataLength
)) == KERN_SUCCESS
)
920 results
[resultsAmount
++] = address
;
925 if ( result
!= KERN_PROTECTION_FAILURE
)
927 NSLog( @
"vm_read_overwrite returned error: %i", result
);
933 realloc( results
, TCAddressSize
*resultsAmount
);
934 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_INTEGER size
:SIZE_32_BIT data
:results amount
:resultsAmount
]];
936 NSLog( @
"found %i of %i", resultsAmount
, value
);
939 - (void)searchDecimalFloat
:(float)value
941 kern_return_t result
;
944 vm_size_t dataLength
;
947 int resultsAmount
= 0;
949 SearchResults
*lastResults
= [searchResults lastObject
];
950 TCaddress
*lastResultsData
= [lastResults data
];
951 int i
, lastResultsAmount
= [lastResults amount
];
953 if ( [lastResults type
] != TYPE_DECIMAL ||
[lastResults size
] != SIZE_32_BIT
)
955 [self sendError
:@
"This search is incompatible with the previous search." fatal
:NO
];
959 if ( (results
= (TCaddress
*)malloc( TCAddressSize
*lastResultsAmount
)) == NULL
)
961 NSLog( @
"ERROR: could not create buffer" );
963 [self sendError
:@
"The server cancelled the search because it ran out of memory." fatal
:NO
];
967 for ( i
= 0; i
< lastResultsAmount
; i
++ )
969 TCaddress address
= lastResultsData
[i
];
971 dataLength
= sizeof(data
);
973 if ( (result
= vm_read_overwrite( processTask
, address
, sizeof(data
), (vm_address_t
)(&data
), &dataLength
)) == KERN_SUCCESS
)
975 if ( cl_compare_float_eps( data
, value
, 0.1f
) == 0 )
977 results
[resultsAmount
++] = address
;
982 if ( result
!= KERN_PROTECTION_FAILURE
)
984 NSLog( @
"vm_read_overwrite returned error: %i", result
);
990 realloc( results
, TCAddressSize
*resultsAmount
);
991 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_DECIMAL size
:SIZE_32_BIT data
:results amount
:resultsAmount
]];
993 NSLog( @
"found %i of %i", resultsAmount
, value
);
996 - (void)searchDecimalDouble
:(double)value
998 kern_return_t result
;
1001 vm_size_t dataLength
;
1004 int resultsAmount
= 0;
1006 SearchResults
*lastResults
= [searchResults lastObject
];
1007 TCaddress
*lastResultsData
= [lastResults data
];
1008 int i
, lastResultsAmount
= [lastResults amount
];
1010 if ( [lastResults type
] != TYPE_DECIMAL ||
[lastResults size
] != SIZE_64_BIT
)
1012 [self sendError
:@
"This search is incompatible with the previous search." fatal
:NO
];
1016 if ( (results
= (TCaddress
*)malloc( TCAddressSize
*lastResultsAmount
)) == NULL
)
1018 NSLog( @
"ERROR: could not create buffer" );
1020 [self sendError
:@
"The server cancelled the search because it ran out of memory." fatal
:NO
];
1024 for ( i
= 0; i
< lastResultsAmount
; i
++ )
1026 TCaddress address
= lastResultsData
[i
];
1028 dataLength
= sizeof(data
);
1030 if ( (result
= vm_read_overwrite( processTask
, address
, sizeof(data
), (vm_address_t
)(&data
), &dataLength
)) == KERN_SUCCESS
)
1032 if ( cl_compare_double_eps( data
, value
, 0.1 ) == 0 )
1034 results
[resultsAmount
++] = address
;
1039 if ( result
!= KERN_PROTECTION_FAILURE
)
1041 NSLog( @
"vm_read_overwrite returned error: %i", result
);
1047 realloc( results
, TCAddressSize
*resultsAmount
);
1048 [searchResults addObject
:[SearchResults resultsWithType
:TYPE_DECIMAL size
:SIZE_64_BIT data
:results amount
:resultsAmount
]];
1050 NSLog( @
"found %i of %i", resultsAmount
, value
);
1054 - (void)changeString8bit
:(char const *)value size
:(int)vsize addresses
:(TCaddress
*)addresses count
:(int)count
1059 NSLog( @
"change string: %s", value
);
1061 for ( i
= 0; i
< count
; i
++ )
1063 if ( vm_write( processTask
, (vm_address_t
)addresses
[i
], (vm_offset_t
)value
, vsize
) != KERN_SUCCESS
)
1069 if ( failCount
> 0 )
1071 [self sendError
:[NSString stringWithFormat
:@
"%i of the selected variables could not be changed.", failCount
] fatal
:NO
];
1075 - (void)changeIntegerChar
:(int8_t
)value addresses
:(TCaddress
*)addresses count
:(int)count
1080 for ( i
= 0; i
< count
; i
++ )
1082 if ( vm_write( processTask
, (vm_address_t
)addresses
[i
], (vm_offset_t
)(&value
), sizeof(value
) ) != KERN_SUCCESS
)
1088 if ( failCount
> 0 )
1090 [self sendError
:[NSString stringWithFormat
:@
"%i of the selected variables could not be changed.", failCount
] fatal
:NO
];
1094 - (void)changeIntegerShort
:(int16_t
)value addresses
:(TCaddress
*)addresses count
:(int)count
1099 for ( i
= 0; i
< count
; i
++ )
1101 if ( vm_write( processTask
, (vm_address_t
)addresses
[i
], (vm_offset_t
)(&value
), sizeof(value
) ) != KERN_SUCCESS
)
1107 if ( failCount
> 0 )
1109 [self sendError
:[NSString stringWithFormat
:@
"%i of the selected variables could not be changed.", failCount
] fatal
:NO
];
1113 - (void)changeIntegerLong
:(int32_t
)value addresses
:(TCaddress
*)addresses count
:(int)count
1118 for ( i
= 0; i
< count
; i
++ )
1120 if ( vm_write( processTask
, (vm_address_t
)addresses
[i
], (vm_offset_t
)(&value
), sizeof(value
) ) != KERN_SUCCESS
)
1126 if ( failCount
> 0 )
1128 [self sendError
:[NSString stringWithFormat
:@
"%i of the selected variables could not be changed.", failCount
] fatal
:NO
];
1132 - (void)changeDecimalFloat
:(float)value addresses
:(TCaddress
*)addresses count
:(int)count
1137 for ( i
= 0; i
< count
; i
++ )
1139 if ( vm_write( processTask
, (vm_address_t
)addresses
[i
], (vm_offset_t
)(&value
), sizeof(value
) ) != KERN_SUCCESS
)
1145 if ( failCount
> 0 )
1147 [self sendError
:[NSString stringWithFormat
:@
"%i of the selected variables could not be changed.", failCount
] fatal
:NO
];
1151 - (void)changeDecimalDouble
:(double)value addresses
:(TCaddress
*)addresses count
:(int)count
1156 for ( i
= 0; i
< count
; i
++ )
1158 if ( vm_write( processTask
, (vm_address_t
)addresses
[i
], (vm_offset_t
)(&value
), sizeof(value
) ) != KERN_SUCCESS
)
1164 if ( failCount
> 0 )
1166 [self sendError
:[NSString stringWithFormat
:@
"%i of the selected variables could not be changed.", failCount
] fatal
:NO
];
1171 - (void)sendProcessList
1173 NSArray
*processList
= [rootProxy serverProcessList
];
1179 PacketHeader header
;
1184 int length
= sizeof(u_int32_t
);
1187 u_int32_t processCount
= [processList count
];
1189 int i
, max
= processCount
;
1191 header.checksum
= RandomChecksum();
1192 header.function
= 2;
1194 for ( i
= 0; i
< max
; i
++ )
1196 pid
= [[processList objectAtIndex
:i
] objectForKey
:@
"NSApplicationProcessIdentifier"];
1197 name
= [[processList objectAtIndex
:i
] objectForKey
:@
"NSApplicationName"];
1200 length
+= sizeof(u_int32_t
) + [name length
] + 1;
1203 header.size
= length
;
1204 length
+= sizeof(header
);
1207 if ( (buffer
= (char *)malloc( length
))==NULL
)
1209 NSLog( @
"sendProcessList failed" );
1215 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
1216 COPY_TO_BUFFER( ptr
, &processCount
, sizeof(processCount
) );
1218 for ( i
= 0; i
< max
; i
++ )
1220 pidNum
= [[[processList objectAtIndex
:i
] objectForKey
:@
"NSApplicationProcessIdentifier"] unsignedLongValue
];
1221 name
= [[processList objectAtIndex
:i
] objectForKey
:@
"NSApplicationName"];
1223 COPY_TO_BUFFER( ptr
, &pidNum
, sizeof(pid
) );
1224 COPY_TO_BUFFER( ptr
, [name lossyCString
], [name length
] + 1 );
1227 lengthAfter
= length
;
1229 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
1231 NSLog( @
"sendProcessList failed" );
1238 - (void)sendSearchFinished
1240 PacketHeader header
;
1241 int length
= sizeof(header
);
1243 header.checksum
= RandomChecksum();
1244 header.function
= 6;
1247 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
1249 NSLog( @
"sendSearchFinished failed" );
1253 - (void)sendVariableList
:(TCaddress
const *)data amount
:(int)amount
1255 PacketHeader header
;
1261 header.checksum
= RandomChecksum();
1262 header.function
= 7;
1263 header.size
= sizeof(amount
) + TCAddressSize
*amount
;
1266 lengthAfter
= length
= header.size
+ sizeof(header
);
1268 if ( (buffer
= (char *)malloc( length
)) == NULL
)
1270 NSLog( @
"sendVariableList:amount: failed" );
1276 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
1277 COPY_TO_BUFFER( ptr
, &amount
, sizeof(amount
) );
1278 COPY_TO_BUFFER( ptr
, data
, TCAddressSize
*amount
);
1280 if ( SendBuffer( sockfd
, buffer
, &length
) == -1 || lengthAfter
!= length
)
1282 NSLog( @
"sendVariableList:amount: failed" );
1288 - (void)sendChangeFinished
1290 PacketHeader header
;
1291 int length
= sizeof(header
);
1293 header.checksum
= RandomChecksum();
1294 header.function
= 9;
1297 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
1299 NSLog( @
"sendChangeFinished failed" );
1303 - (void)sendError
:(NSString
*)msg fatal
:(BOOL)fatal
1305 PacketHeader header
;
1309 u_int32_t type
= (fatal
)?
1:0;
1313 header.checksum
= RandomChecksum();
1314 header.function
= 11;
1315 header.size
= sizeof(type
) + [msg length
] + 1;
1318 lengthAfter
= length
= header.size
+ sizeof(header
);
1320 if ( (buffer
= (char *)malloc( length
)) == NULL
)
1322 NSLog( @
"sendError:fatal: failed" );
1328 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
1329 COPY_TO_BUFFER( ptr
, &type
, sizeof(type
) );
1330 COPY_TO_BUFFER( ptr
, [msg lossyCString
], [msg length
] + 1 );
1332 if ( SendBuffer( sockfd
, buffer
, &length
) == -1 || lengthAfter
!= length
)
1334 NSLog( @
"sendError:fatal: failed" );
1340 - (void)sendVariableValue
:(u_int32_t
)index
1345 - (void)sendUndoFinished
1347 PacketHeader header
;
1348 int length
= sizeof(header
);
1350 header.checksum
= RandomChecksum();
1351 header.function
= 15;
1354 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
1356 NSLog( @
"sendUndoFinished failed" );
1360 - (void)sendRedoFinished
1362 PacketHeader header
;
1363 int length
= sizeof(header
);
1365 header.checksum
= RandomChecksum();
1366 header.function
= 17;
1369 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
1371 NSLog( @
"sendRedoFinished failed" );
1375 - (void)sendUndoRedoStatus
1377 PacketHeader header
;
1381 u_int32_t undoCount
= (u_int32_t
)[searchResults count
];
1382 u_int32_t redoCount
= (u_int32_t
)[searchResultsUndone count
];
1386 header.checksum
= RandomChecksum();
1387 header.function
= 19;
1388 header.size
= 2 * sizeof(u_int32_t
);
1390 length
= lengthAfter
= sizeof(header
) + header.size
;
1392 if ( (buffer
= (char *)malloc( length
)) == NULL
)
1394 NSLog( @
"sendSetTargetPID: failed" );
1399 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
1400 COPY_TO_BUFFER( ptr
, &undoCount
, sizeof(undoCount
) );
1401 COPY_TO_BUFFER( ptr
, &redoCount
, sizeof(redoCount
) );
1403 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
1405 NSLog( @
"sendUndoRedoStatus: failed" );
1411 - (void)sendAppLaunched
:(NSDictionary
*)appInfo
1413 PacketHeader header
;
1420 u_int32_t pid
= [[appInfo objectForKey
:@
"NSApplicationProcessIdentifier"] unsignedLongValue
];
1421 NSString
*name
= [appInfo objectForKey
:@
"NSApplicationName"];
1424 length
+= sizeof(u_int32_t
) + [name length
] + 1;
1426 header.checksum
= RandomChecksum();
1427 header.function
= 21;
1428 header.size
= length
;
1430 length
+= sizeof(header
);
1433 if ( (buffer
= (char *)malloc( length
))==NULL
)
1435 NSLog( @
"sendAppLaunched: failed" );
1442 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
1443 COPY_TO_BUFFER( ptr
, &pid
, sizeof(pid
) );
1444 COPY_TO_BUFFER( ptr
, [name lossyCString
], [name length
] + 1 );
1446 lengthAfter
= length
;
1448 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
1450 NSLog( @
"sendAppLaunched: failed" );
1457 - (void)sendAppQuit
:(NSDictionary
*)appInfo
1459 PacketHeader header
;
1466 u_int32_t pid
= [[appInfo objectForKey
:@
"NSApplicationProcessIdentifier"] unsignedLongValue
];
1469 length
+= sizeof(pid
);
1471 header.checksum
= RandomChecksum();
1472 header.function
= 22;
1473 header.size
= length
;
1475 length
+= sizeof(header
);
1478 if ( (buffer
= (char *)malloc( length
))==NULL
)
1480 NSLog( @
"sendAppQuit: failed" );
1487 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
1488 COPY_TO_BUFFER( ptr
, &pid
, sizeof(pid
) );
1490 lengthAfter
= length
;
1492 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
1494 NSLog( @
"sendAppQuit: failed" );
1500 - (void)sendTargetAppQuit
1502 PacketHeader header
;
1503 int length
= sizeof(header
);
1505 header.checksum
= RandomChecksum();
1506 header.function
= 23;
1509 if ( SendBuffer( sockfd
, (char *)(&header
), &length
) == -1 || length
!= sizeof(header
) )
1511 NSLog( @
"sendTargetAppQuit failed" );
1515 - (void)sendPauseFinished
:(BOOL)paused
1517 PacketHeader header
;
1522 int length
= sizeof(paused
);
1525 header.checksum
= RandomChecksum();
1526 header.function
= 24;
1527 header.size
= length
;
1529 length
+= sizeof(header
);
1532 if ( (buffer
= (char *)malloc( length
))==NULL
)
1534 NSLog( @
"sendPauseFinished: failed" );
1541 COPY_TO_BUFFER( ptr
, &header
, sizeof(header
) );
1542 COPY_TO_BUFFER( ptr
, &paused
, sizeof(paused
) );
1544 lengthAfter
= length
;
1546 if ( SendBuffer( sockfd
, buffer
, &lengthAfter
) == -1 || lengthAfter
!= length
)
1548 NSLog( @
"sendPauseFinished: failed" );
1555 - (void)handleClearSearch
1557 [searchResults removeAllObjects
];
1558 [searchResultsUndone removeAllObjects
];
1563 - (void)handleSearch
:(char const *)data size
:(int)dataSize
1568 char *ptr
= (char *)data
;
1570 [self setAction
:@
"Searching"];
1572 COPY_FROM_BUFFER( &type
, ptr
, sizeof(type
) );
1573 COPY_FROM_BUFFER( &size
, ptr
, sizeof(size
) );
1575 if ( ![searchResults lastObject
] )
1585 [self firstSearchString8bit
:ptr size
:(dataSize
- (ptr
- data
))];
1600 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1601 [self firstSearchIntegerChar
:value
];
1609 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1610 [self firstSearchIntegerShort
:value
];
1618 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1619 [self firstSearchIntegerLong
:value
];
1634 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1635 [self firstSearchDecimalFloat
:value
];
1643 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1644 [self firstSearchDecimalDouble
:value
];
1662 [self searchString8bit
:ptr size
:(dataSize
- (ptr
- data
))];
1678 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1679 [self searchIntegerChar
:value
];
1688 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1689 [self searchIntegerShort
:value
];
1698 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1699 [self searchIntegerLong
:value
];
1715 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1716 [self searchDecimalFloat
:value
];
1724 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1725 [self searchDecimalDouble
:value
];
1734 [self sendVariableList
:[(SearchResults
*)[searchResults lastObject
] data
] amount
:[[searchResults lastObject
] amount
]];
1735 [self sendSearchFinished
];
1736 [self sendUndoRedoStatus
];
1738 [self setAction
:nil];
1741 - (void)handleChange
:(char const *)data size
:(int)dataSize
1746 TCaddress
*addresses
= NULL
;
1749 char *ptr
= (char *)data
;
1751 [self setAction
:@
"Changing"];
1753 // read out the type and size of the variable.
1754 COPY_FROM_BUFFER( &type
, ptr
, sizeof(type
) );
1755 COPY_FROM_BUFFER( &size
, ptr
, sizeof(size
) );
1757 // read the amount of addresses.
1758 COPY_FROM_BUFFER( &count
, ptr
, sizeof(count
) );
1760 // save the pointer to the addresses.
1761 addresses
= (TCaddress
*)ptr
;
1762 ptr
+= TCAddressSize
*count
;
1772 [self changeString8bit
:ptr size
:(dataSize
- (ptr
- data
)) addresses
:addresses count
:count
];
1787 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1788 [self changeIntegerChar
:value addresses
:addresses count
:count
];
1796 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1797 [self changeIntegerShort
:value addresses
:addresses count
:count
];
1805 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1806 [self changeIntegerLong
:value addresses
:addresses count
:count
];
1821 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1822 [self changeDecimalFloat
:value addresses
:addresses count
:count
];
1830 COPY_FROM_BUFFER( &value
, ptr
, sizeof(value
) );
1831 [self changeDecimalDouble
:value addresses
:addresses count
:count
];
1839 [self sendChangeFinished
];
1841 [self setAction
:nil];
1844 - (void)handlePauseTarget
1846 if ( !processPaused
)
1852 if ( ptrace( PT_ATTACH
, processID
, 0, 0 ) != -1 )
1854 if ( waitpid( processID
, &wait_status
, WUNTRACED
) == processID
)
1856 if ( WIFSTOPPED(wait_status
) )
1858 processPaused
= YES
;
1859 [self sendPauseFinished
:YES
];
1863 NSLog( @
"ERROR: process couldn't be paused" );
1864 [self sendPauseFinished
:NO
];
1865 [self sendError
:@
"Could not pause target because of an unknown error." fatal
:NO
];
1870 NSLog( @
"ERROR: process couldn't be paused" );
1871 [self sendPauseFinished
:NO
];
1872 [self sendError
:@
"Could not pause target because of an unknown error." fatal
:NO
];
1877 NSLog( @
"ERROR: process couldn't be paused" );
1878 [self sendPauseFinished
:NO
];
1883 [self sendError
:@
"Could not pause target because there is no valid target to pause." fatal
:NO
];
1887 [self sendError
:@
"Could not pause target because a process cannot pause itself." fatal
:NO
];
1891 [self sendError
:@
"Could not pause target because the target is being controlled by another instance or application." fatal
:NO
];
1895 [self sendError
:@
"Could not pause target because this type of application cannot be paused." fatal
:NO
];
1899 [self sendError
:@
"Could not pause target because of an unknown error." fatal
:NO
];
1906 [self sendPauseFinished
:NO
];
1907 [self sendError
:[NSString stringWithFormat
:@
"Could not pause target because an exception (%@) was raised: %@", [localException name
], [localException reason
]] fatal
:NO
];
1913 ptrace( PT_DETACH
, processID
, 0, 0 );
1916 [self sendPauseFinished
:NO
];
1922 SearchResults
*results
= [searchResults lastObject
];
1926 [searchResultsUndone addObject
:results
];
1927 [searchResults removeLastObject
];
1930 results
= [searchResults lastObject
];
1933 [self sendVariableList
:[results data
] amount
:[results amount
]];
1937 [self sendVariableList
:NULL amount
:0];
1940 [self sendUndoFinished
];
1941 [self sendUndoRedoStatus
];
1946 SearchResults
*results
= [searchResultsUndone lastObject
];
1950 [searchResults addObject
:results
];
1951 [searchResultsUndone removeLastObject
];
1954 results
= [searchResults lastObject
];
1957 [self sendVariableList
:[results data
] amount
:[results amount
]];
1961 [self sendVariableList
:NULL amount
:0];
1964 [self sendRedoFinished
];
1965 [self sendUndoRedoStatus
];
1968 - (void)handleSetTargetPID
:(char const *)data size
:(int)size
1970 char *ptr
= (char *)data
;
1974 COPY_FROM_BUFFER( &pid
, ptr
, sizeof(pid
) );
1982 if ( processPaused
)
1984 [self handlePauseTarget
];
1988 - (void)setPID
:(pid_t
)pid
1990 kern_return_t result
;
1996 if ( (result
= task_for_pid( current_task(), processID
, &processTask
)) != KERN_SUCCESS
)
1998 NSLog( @
"task_for_pid returned error: %i", result
);
2007 [[[NSWorkspace sharedWorkspace
] notificationCenter
] removeObserver
:self];
2009 [searchResults release
];
2010 [searchResultsUndone release
];
2016 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2017 %%%%%%%%%%%%%%%%%%%%%% NSWorkspaceDidLaunchApplicationNotification Notification
2018 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
2021 - (void)processListChanged
:(NSNotification
*)note
2023 pid_t pid
= [[[note userInfo
] objectForKey
:@
"NSApplicationProcessIdentifier"] intValue
];
2025 if ( /*pid != getpid()*/ sockfd
!= -1 )
2027 if ( [[note name
] isEqualToString
:@
"NSWorkspaceDidLaunchApplicationNotification"] )
2029 [self sendAppLaunched
:[note userInfo
]];
2033 [self sendAppQuit
:[note userInfo
]];
2035 if ( pid
== processID
)
2037 [self sendTargetAppQuit
];
2039 // we can't set the new target here because this method is not called
2040 // in the server thread. the client will have to change it.
2041 //[self setPID:[rootProxy serverFirstProcess]];
2052 /*%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2053 %%%%%%%%%%%%%%%%%%%%%% Internal Functions
2054 %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%*/
2057 BOOL compare_float( float a, float b )
2059 float const feps = 0.0001f;
2061 return feps > fabsf( a - b );
2064 BOOL compare_double( double a, double b )
2066 double const deps = 0.0000001;
2068 return deps > fabs( a - b );