I'm trying to get TCP open port list in iphone by using sysctlbyname().
sysctlbyname(const char *name, void *oldp, size_t *oldlenp, void *newp,
size_t newlen);
.
#include <sys/sysctl.h>
size_t len = 0;
if (sysctlbyname("net.inet.tcp.pcblist", 0, &len, 0, 0) < 0) {
perror("sysctlbyname");
} else {
char *buf = malloc(len);
//printf("%d",sizeof(buf));
sysctlbyname("net.inet.tcp.pcblist", buf, &len, 0, 0);
NSData *data = [NSData dataWithBytesNoCopy:buf length:len];
NSLog(#"data = %#", data);
//printf("%d",sizeof(buf));
//printf("%s",buf);
}
The information is copied into the buffer specified by oldp.
OUTPUT::
data = <18000000 34000000 d8160000 00000000 7d760000 00000000 0c020000 00000000 00000000 00000000 00000000 0050c598 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000 c2160000 00000000 40008000 00000000 01400000
Buffer is filled with data here.but I'm unable to print the data in readable format.converting this data into NSString won't help as internally buffer has its own structure.
Anyone knows how to obtain TCP open port list as output from this data?
Thanks.
copy netstat code from BSD source.
see the printproto() function in main.c
This will explore all related to this buffer and how to get TCP port list.
Thanks.
Related
After I start using getaddrinfo() to retrieve dynamic IP addresses, the sendTo() of my socket no longer works and returns error "Segmentation fault (core dumped)". Why is that happening, is there any initialization or memory allocation missing in my codes please? I've tried quite a while but haven't figured out the reason. Any help would be really appreciated!
Here is the portion of codes :
// variables declaration
int s;
struct sockaddr_in si_other;
struct addrinfo hints;
struct addrinfo *result, *rp;
char *hostname = "localhost";
const char* portnum = "8000";
// settings of hints
memset(&hints, 0, sizeof(struct addrinfo));
hints.ai_family = AF_UNSPEC; /* Allow IPv4 or IPv6 */
hints.ai_socktype = SOCK_DGRAM; /* Datagram socket */
hints.ai_flags = 0;
hints.ai_protocol = 0;
hints.ai_flags = AI_NUMERICSERV;
// resolve dynamically IP adress by getaddrinfo()
s = getaddrinfo(hostname, NULL, &hints, &result);
if (s != 0) {
fprintf(stderr, "getaddrinfo: %s\n", gai_strerror(s));exit(EXIT_FAILURE);
}
// create socket s
for (rp = result; rp != NULL; rp = rp->ai_next)
{
s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
}
// loop for sending m x struct ECA_message_t
int m=0;
for (; m<NbMesPerFile; ++m)
{
ECA_message_t* ECA_paquet;
ECA_paquet=(ECA_message_t*)malloc(sizeof(ECA_message_t)*2400);
// 2400 to workaround some not understood memory issue and make sendto() to
// work
// function initializing ECA_paquet
Client_update_ECA_data(ECA_paquet,m);
if (sendto(s, ECA_paquet, sizeof(ECA_paquet)*2400, 0 ,(struct
sockaddr*)&si_other,slen)==-1)
{
perror("sendto()");
}
}
To add details to my struct, and to find why my malloc(sizeof(ECA_message_t) goes wrong, please see below the codes for struct ECA_message_t :
typedef struct{
unsigned int version:2;
unsigned int p:1;
unsigned int x:1;
unsigned int cc:4;
unsigned int m:1;
unsigned int pt:7;
unsigned int seq:16;
u_int32_t timestamp;
u_int32_t ssrc;
u_int32_t csrc;
} RTP_header_t; // 16 bytes
typedef struct {
unsigned int version:2;
unsigned int reserved_1:6;
unsigned int reserved_2:8;
unsigned int number_sample:16;
}ECA_header_t; // 4 bytes
typedef struct {
//every line composed of 6 values, 2 byte per value, all signed
int32_t v_phase_1;
int32_t v_phase_2;
int32_t v_phase_3;
int32_t i_phase_1;
int32_t i_phase_2;
int32_t i_phase_3;
}ECA_payload_t; // 12 bytes
typedef struct {
RTP_header_t rtp_header;
ECA_header_t eca_header;
ECA_payload_t eca_payload[MAX_ECA_SAMPLES]; // MAX_ECA_SAMPLES of 100
}ECA_message_t; // 1220 bytes
Here is the Aborted (Core dumpted) Back trace message :
*** glibc detected *** ./clientUDPIniDyn: double free or corruption (!prev): 0x081768c8 ***
======= Backtrace: =========
/lib/i386-linux-gnu/libc.so.6(+0x75ee2)[0xb7642ee2]
./clientUDPIniDyn[0x804896b]
/lib/i386-linux-gnu/libc.so.6(__libc_start_main+0xf3)[0xb75e64d3]
./clientUDPIniDyn[0x80486b1]
======= Memory map: ========
08048000-0804a000 r-xp 00000000 08:01 1319522 /home/lin/ULB/Memoire/Client_Server
/Server/clientUDPIniDyn
0804a000-0804b000 r--p 00001000 08:01 1319522 /home/lin/ULB/Memoire/Client_Server
/Server/clientUDPIniDyn
0804b000-0804c000 rw-p 00002000 08:01 1319522 /home/lin/ULB/Memoire/Client_Server
/Server/clientUDPIniDyn
08176000-08197000 rw-p 00000000 00:00 0 [heap]
b7589000-b75a5000 r-xp 00000000 08:05 264147 /lib/i386-linux-gnu/libgcc_s.so.1
b75a5000-b75a6000 r--p 0001b000 08:05 264147 /lib/i386-linux-gnu/libgcc_s.so.1
b75a6000-b75a7000 rw-p 0001c000 08:05 264147 /lib/i386-linux-gnu/libgcc_s.so.1
b75bf000-b75ca000 r-xp 00000000 08:05 293796 /lib/i386-linux-gnu/libnss_files-
2.15.so
b75ca000-b75cb000 r--p 0000a000 08:05 293796 /lib/i386-linux-gnu/libnss_files-
2.15.so
b75cb000-b75cc000 rw-p 0000b000 08:05 293796 /lib/i386-linux-gnu/libnss_files-
2.15.so
b75cc000-b75cd000 rw-p 00000000 00:00 0
b75cd000-b7770000 r-xp 00000000 08:05 293791 /lib/i386-linux-gnu/libc-2.15.so
b7770000-b7771000 ---p 001a3000 08:05 293791 /lib/i386-linux-gnu/libc-2.15.so
b7771000-b7773000 r--p 001a3000 08:05 293791 /lib/i386-linux-gnu/libc-2.15.so
b7773000-b7774000 rw-p 001a5000 08:05 293791 /lib/i386-linux-gnu/libc-2.15.so
b7774000-b7777000 rw-p 00000000 00:00 0
b778d000-b7791000 rw-p 00000000 00:00 0
b7791000-b7792000 r-xp 00000000 00:00 0 [vdso]
b7792000-b77b2000 r-xp 00000000 08:05 293804 /lib/i386-linux-gnu/ld-2.15.so
b77b2000-b77b3000 r--p 0001f000 08:05 293804 /lib/i386-linux-gnu/ld-2.15.so
b77b3000-b77b4000 rw-p 00020000 08:05 293804 /lib/i386-linux-gnu/ld-2.15.so
bfbad000-bfbce000 rw-p 00000000 00:00 0 [stack]
Aborted (core dumped)
Here are fixed codes, no more segmentation fault by using calloc()
for (rp = result; rp != NULL; rp = rp->ai_next)
{
s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol); // socket creation
ECA_message_t* ECA_paquet;
ECA_paquet=calloc(NbMesPerFile, sizeof(* ECA_paquet)); // calloc to assign table [NbMesPerFile] length bloc memory for my struct EA_message_t
// sending m paquets of my struct
int m=0;
for (; m<NbMesPerFile; ++m)
{
Client_update_ECA_data(ECA_paquet,m); //update the ECA data paquet
if (sendto(s,ECA_paquet, sizeof(*ECA_paquet) ,0, rp->ai_addr,rp->ai_addrlen)==-1) // send data ECA data pointed by ECA_paquet
{
perror("sendto()");
}
}
}
// create socket s
for (rp = result; rp != NULL; rp = rp->ai_next)
{
s = socket(rp->ai_family, rp->ai_socktype, rp->ai_protocol);
}
You are leaking filedescriptors (sockets) here. With every iteration of the loop s is reassigned. And the previous value of s is lost. (I don't know how long your linked list is)
// loop for sending m x struct ECA_message_t
int m=0;
for (; m<NbMesPerFile; ++m)
{
ECA_message_t* ECA_paquet;
ECA_paquet=(ECA_message_t*)malloc(sizeof(ECA_message_t)*2400);
// 2400 to workaround some not understood memory issue and make sendto() to
// work
// function initializing ECA_paquet
Client_update_ECA_data(ECA_paquet,m);
if (sendto(s, ECA_paquet, sizeof(ECA_paquet)*2400, 0 ,(struct
sockaddr*)&si_other,slen)==-1)
{
perror("sendto()");
}
}
You are leaking memory here. With every iteration of the loop ECA_paquet is reassigned. And the previous value of ECA_paquet is lost. Forever. (I don't know how large NbMesPerFile is)
(this is probably not the cause of your segfault, but it at least indicates substandard quality) You should also not cast the return value of malloc(), (+ #include <stdlib.h>, , plus check malloc()s return value. And turn up the warning level of your compiler.
My application get access violation sometimes.
I runned application through windbg, and it stopped in the following function .
also tried _vscprintf instead of vsnprintf, and the result was same.
I 'm newbie about windbg.
Any help will be appreciated.
int tsk_sprintf_2(char** str, const char* format, va_list* ap)
{
int len = 0;
va_list ap2;
ap2 = *ap;
len = vsnprintf(0, 0, format, *ap); /*-> access violation in this point! */
*str = (char*)calloc(1, len+1);
vsnprintf(*str, len, format, ap2);
va_end(ap2);
return len;
}
==> the following are the result from windbg
MANAGED_STACK: !dumpstack -EE
OS Thread Id: 0x5b8 (22)
Current frame:
ChildEBP RetAddr Caller, Callee
PRIMARY_PROBLEM_CLASS: WRONG_SYMBOLS
BUGCHECK_STR: APPLICATION_FAULT_WRONG_SYMBOLS
LAST_CONTROL_TRANSFER: from 1026d3d8 to 102e14cf
STACK_TEXT:
WARNING: Stack unwind information not available. Following frames may be wrong.
1d3cde7c 1026d3d8 1d3cdea8 0898eeeb 00000000 MSVCR100D!vcwprintf_s_l+0x52ef
1d3cded0 1026d46c 00000000 00000000 0898ee88 MSVCR100D!vsnprintf_l+0x158
1d3cdeec 0834d927 00000000 00000000 0898ee88 MSVCR100D!vsnprintf+0x1c
1d3cdfe8 1002891e 1d3ce0d0 0898ee88 1d3ce1e4 tinySAK!tsk_sprintf_2+0x57
1d3ce0f0 10028b77 09a16fe8 0898ee88 00000000 tinyWRAP!debug_xxx_cb+0x6e
1d3ce1ec 088b697b 09a16fe8 0898ee88 00000444 tinyWRAP!DDebugCallback::debug_info_cb+0x37
1d3cffb4 7c80b713 1cd10f90 1d2cfb44 7c947d9a tinyNET!tnet_transport_mainthread+0x1adb
1d3cffec 00000000 088a2aff 1cd10f90 00000000 KERNEL32!GetModuleFileNameA+0x1b4
SYMBOL_STACK_INDEX: 0
SYMBOL_NAME: msvcr100d!vcwprintf_s_l+52ef
FOLLOWUP_NAME: MachineOwner
MODULE_NAME: MSVCR100D
IMAGE_NAME: MSVCR100D.dll
STACK_COMMAND: ~22s ; kb
BUCKET_ID: WRONG_SYMBOLS
FAILURE_BUCKET_ID: WRONG_SYMBOLS_c0000005_MSVCR100D.dll!vcwprintf_s_l
WATSON_STAGEONE_URL:
Followup: MachineOwner
---------
route.
You're attempting to print into a NULL pointer: len = vsnprintf(0, 0, format, *ap);; of course, it will crash. Send a valid address of output buffer as the first parameter and valid length as second.
I have a simple test program causing an infinite wait on lock.
public class SyncBlock
{
}
class Program
{
public static SyncBlock sync = new SyncBlock();
private static void ThreadProc()
{
try
{
Monitor.Enter(sync);
}
catch (Exception)
{
//Monitor.Exit(sync);
Console.WriteLine("3rd party code threw an exception");
}
}
static void Main(string[] args)
{
Thread newThread = new Thread(ThreadProc);
newThread.Start();
Console.WriteLine("Acquiring lock");
Monitor.Enter(sync);
Console.WriteLine("Releasing lock");
Monitor.Exit(sync);
}
}
So the main thread is basically get locked when it tries to do Monitor.Enter(sync). If I looked at !clrStack on main thread, its output basically show it which make sense but when I try to see native side of stack, I am expecting to see some Wait on single/multiple object type of call but I don't see it. Can anyone explain it. Thanks
0:000> !CLRStack
PDB symbol for mscorwks.dll not loaded
OS Thread Id: 0x1e8 (0)
ESP EIP
0012f0a8 77455e74 [GCFrame: 0012f0a8]
0012f178 77455e74 [HelperMethodFrame_1OBJ: 0012f178] System.Threading.Monitor.Enter (System.Object)
0012f1d0 00a40177 ConsoleApplication1.Program.Main(System.String[])
0012f400 70fc1b4c [GCFrame: 0012f400]
0:000> kb
ChildEBP RetAddr Args to Child
WARNING: Stack unwind information not available. Following frames may be wrong.
0012eeb4 710afb92 0012ee68 002d6280 00000000 ntdll!KiFastSystemCallRet
0012ef1c 710af7c3 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer+0x1b1f2
0012ef3c 710af8cc 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer+0x1ae23
0012efc0 710af961 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer+0x1af2c
0012f010 710afae1 00000001 002d6280 00000000 mscorwks!StrongNameFreeBuffer+0x1afc1
0012f06c 70fdc5ae ffffffff 00000001 00000000 mscorwks!StrongNameFreeBuffer+0x1b141
0012f080 710df68a ffffffff 00000001 00000000 mscorwks!LogHelp_NoGuiOnAssert+0x10562
0012f10c 710b1154 002aad90 ffffffff 002aad90 mscorwks!StrongNameFreeBuffer+0x4acea
0012f128 710b10d8 42b8b47d 00000000 002aad90 mscorwks!StrongNameFreeBuffer+0x1c7b4
0012f1e0 70fc1b4c 0012f1f0 0012f230 0012f270 mscorwks!StrongNameFreeBuffer+0x1c738
0012f1f0 70fd2219 0012f2c0 00000000 0012f290 mscorwks+0x1b4c
0012f270 70fe6591 0012f2c0 00000000 0012f290 mscorwks!LogHelp_NoGuiOnAssert+0x61cd
0012f3ac 70fe65c4 0023c038 0012f478 0012f444 mscorwks!CoUninitializeEE+0x2ead
0012f3c8 70fe65e2 0023c038 0012f478 0012f444 mscorwks!CoUninitializeEE+0x2ee0
0012f3e0 7103389d 0012f444 42b8b0f1 00000000 mscorwks!CoUninitializeEE+0x2efe
0012f544 710337bd 002332e0 00000001 0012f580 mscorwks!GetPrivateContextsPerfCounters+0xf546
0012f7ac 71033d0d 00000000 42b8b9c9 00000001 mscorwks!GetPrivateContextsPerfCounters+0xf466
0012fc7c 71033ef7 00ce0000 00000000 42b8979 mscorwks!GetPrivateContextsPerfCounters+0xf9b6
0012fccc 71033e27 00ce0000 42b8b8a1 00000000 mscorwks!CorExeMain+0x168
* ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\Microsoft.NET\Framework\v4.0.30319\mscoreei.dll -
0012fd14 71cf55ab 71033d8f 0012fd30 71f37f16 mscorwks!CorExeMain+0x98
* ERROR: Symbol file could not be found. Defaulted to export symbols for C:\Windows\system32\mscoree.dll -
0012fd20 71f37f16 00000000 71cf0000 0012fd44 mscoreei!CorExeMain+0x38
0012fd30 71f34de3 00000000 7723d0e9 7ffd8000 mscoree!CreateConfigStream+0x13f
0012fd44 774319bb 7ffd8000 084952f9 00000000 mscoree!CorExeMain+0x8
0012fd84 7743198e 71f34ddb 7ffd8000 00000000 ntdll!RtlInitializeExceptionChain+0x63
0012fd9c 00000000 71f34ddb 7ffd8000 00000000 ntdll!RtlInitializeExceptionChain+0x36
You have to point windbg to the microsoft windows symbols server to get a good stack trace.
type in the following in your windbg command window:
.sympath srv*c:\websymbols*http://msdl.microsoft.com/download/symbols
Also see this:
Using microsoft symbol server to get symbols
Also, to answer your original question about how to debug this, here is the cookbook:
0:000> !clrstack
OS Thread Id: 0x1358 (0)
ESP EIP
0012f328 7c90e514 [GCFrame: 0012f328]
0012f3f8 7c90e514 [HelperMethodFrame_1OBJ: 0012f3f8] System.Threading.Monitor.Enter(System.Object)
0012f450 00d10177 Program.Main(System.String[])
0012f688 79e71b4c [GCFrame: 0012f688]
In your original program, the background thread was started first. So, it acquired the lock. However it exited without releasing the lock. After that your main thread tried to acquire the lock and it is stuck because the lock is already owned.
How do you find out who owns it? First do a !threads followed by !syncblk.
0:000> !threads
ThreadCount: 3
UnstartedThread: 0
BackgroundThread: 1
PendingThread: 0
DeadThread: 1
Hosted Runtime: no
PreEmptive GC Alloc Lock
ID OSID ThreadOBJ State GC Context Domain Count APT Exception
0 1 1358 0014bb00 200a020 Enabled 00000000:00000000 001540d0 0 MTA
2 2 1360 0015e320 b220 Enabled 00000000:00000000 001540d0 0 MTA (Finalizer)
XXXX 3 0 00175a98 9820 Enabled 00000000:00000000 001540d0 1 Ukn
0:000> !syncblk
Index SyncBlock MonitorHeld Recursion Owning Thread Info SyncBlock Owner
2 0017903c 3 1 00175a98 0 XXX 013503cc SyncBlock
-----------------------------
Total 2
CCW 0
RCW 0
ComClassFactory 0
Free 0
As you can see, !syncblk says that the owining thread object is 00175a98. From the !threads output, you can see that thread object 00175a98 is the dead thread that exited while owning the lock.
Hope this helps.
I have a crash dump and I suspect GDI leaks to be a cause of the crash
From the full crash dump is there anyway to find out the number of GDI handles used by my process when it crashed?
I have created a Windbg script to dump all GDI Handles from the GDI Handle table. See https://aloiskraus.wordpress.com/2016/06/25/show-gdi-handles-by-type-in-windbg/
When you dump it e.g. two times you can see what has changed there:
0:013> $$>a<"D:\GdiDump\DumpGdi.txt"
GDI Handle Table 00000000013e0000 0000000001561000
GDI Handle Count 14
DeviceContexts: 4
Regions: 2
Bitmaps: 2
Palettes: 0
Fonts: 3
Brushes: 3
Pens: 0
Uncategorized: 0
0:013> g
0:014> $$>a<"D:\GdiDump\DumpGdi.txt"
GDI Handle Table 00000000013e0000 0000000001561000
GDI Handle Count 1021
DeviceContexts: 8
Regions: 3
Bitmaps: 1003
Palettes: 0
Fonts: 3
Brushes: 4
Pens: 0
Uncategorized: 0
Here is the script
$$ Run as: $$>a<DumpGdi.txt
$$ Written by Alois Kraus 2016
$$ uses pseudo registers r0-5 and r8-r14
r #$t1=0
r #$t8=0
r #$t9=0
r #$t10=0
r #$t11=0
r #$t12=0
r #$t13=0
r #$t14=0
$$ Increment count is 1 byte until we find a matching field with the current pid
r #$t4=1
r #$t0=$peb
$$ Get address of GDI handle table into t5
.foreach /pS 3 /ps 1 ( #$GdiSharedHandleTable { dt ntdll!_PEB GdiSharedHandleTable #$t0 } ) { r #$t5 = #$GdiSharedHandleTable }
$$ On first call !address produces more output. Do a warmup
.foreach /pS 50 ( #$myStartAddress {!address #$t5} ) { }
$$ Get start address of file mapping into t2
.foreach /pS 4 /ps 40 ( #$myStartAddress {!address #$t5} ) { r #$t2 = #$myStartAddress }
$$ Get end address of file mapping into t3
.foreach /pS 7 /ps 40 ( #$myEndAddress {!address #$t5} ) { r #$t3 = #$myEndAddress }
.printf "GDI Handle Table %p %p", #$t2, #$t3
.for(; #$t2 < #$t3; r #$t2 = #$t2 + #$t4)
{
$$ since we walk bytewise through potentially invalid memory we need first to check if it points to valid memory
.if($vvalid(#$t2,4) == 1 )
{
$$ Check if pid matches
.if (wo(#$t2) == #$tpid )
{
$$ increase handle count stored in $t1 and increase step size by 0x18 because we know the cell structure GDICell has a size of 0x18 bytes.
r #$t1 = #$t1+1
r #$t4 = 0x18
$$ Access wType of GDICELL and increment per GDI handle type
.if (by(#$t2+6) == 0x1 ) { r #$t8 = #$t8+1 }
.if (by(#$t2+6) == 0x4 ) { r #$t9 = #$t9+1 }
.if (by(#$t2+6) == 0x5 ) { r #$t10 = #$t10+1 }
.if (by(#$t2+6) == 0x8 ) { r #$t11 = #$t11+1 }
.if (by(#$t2+6) == 0xa ) { r #$t12 = #$t12+1 }
.if (by(#$t2+6) == 0x10 ) { r #$t13 = #$t13+1 }
.if (by(#$t2+6) == 0x30 ) { r #$t14 = #$t14+1 }
}
}
}
.printf "\nGDI Handle Count %d", #$t1
.printf "\n\tDeviceContexts: %d", #$t8
.printf "\n\tRegions: %d", #$t9
.printf "\n\tBitmaps: %d", #$t10
.printf "\n\tPalettes: %d", #$t11
.printf "\n\tFonts: %d", #$t12
.printf "\n\tBrushes: %d", #$t13
.printf "\n\tPens: %d", #$t14
.printf "\n\tUncategorized: %d\n", #$t1-(#$t14+#$t13+#$t12+#$t11+#$t10+#$t9+#$t8)
It is unlikely since the only debugger extension gdikdx.dll tailored at gdi tasks is not actively maintained since the w2k version and i believe they stopped shipping it since not that many folks are into hacking into gdi internals - according to someone's statement i stumbled upon in a newsgroup - therefore it is no longer invested into.
You're left with only a few options all of which are unfortunately about runtime troubleshooting.
You could start with a tool like nirsoft's GDIView to monitor the use of GDI resources from your app and then progress to any of the runtime instrumentation options:
gdi leaks detector tool described on msdn
bug browser
leaktrap
P.S. could you be more specific on the actual reason of your particular crash?
Tess talks about a similar situation, perhaps this will give you a lead...
http://blogs.msdn.com/tess/archive/2009/02/03/net-memory-leak-to-dispose-or-not-to-dispose-that-s-the-1-gb-question.aspx
Here is an alternative script that dumps the gdi handles from GdiSharedHandleTable it can be used in live usermode / live kernelmode / dump mode
it can also be used in !for_each_process command string to dump gdi handles from all running process in a kernel mode debugging
it uses a .catch block to print the summary
in kd some times the GdiSharedhandleTable page will be paged out / truncated to less than its allocation size The peb header paged out etc problems arise
so this script tries to read as much as it is possible and when a memory access violation happens leaves the catch block and prints a summary of
what it was able to salvage
btw this script is for 32 bit for 64 bit the Pseudo registers need to be adjusted as needed
r $t19=0;r $t18=0;r $t17=0;r $t16=0;r $t15=0;r $t14=0;r $t13=0;r $t12=0;
r $t0 = ##c++(#$Peb->GdiSharedHandleTable)
r $t1 = (##c++(#$Peb->GdiSharedHandleTable) + 0xffffff )
r $t2 = 0
.catch {
.printf /D "<b>gdioffs Kaddr Pid Count Handle Type Tname
IsLive UAddr </b>\n";
.while(#$t0 < #$t1) {
.while( wo(#$t0+4) != #$tpid) {
r $t0 = #$t0+0x10 ; r $t2 = #$t2+1
}
.printf "%08x " , #$t0 ; .printf "%08x " , dwo(#$t0)
.printf "%08x " , wo(#$t0+4) ;.printf "%08x " , wo(#$t0+6)
.printf "%08x " , (wo(#$t0+8)<<0x10)+#$t2 ; .printf "%08x " , by(#$t0+a)
.if( by(#$t0+a) == 1 ) {r $t19=#$t19+1;.printf "DC "}
.elsif( by(#$t0+a) == 4 ) {r $t18=#$t18+1;.printf "Region "}
.elsif( by(#$t0+a) == 5 ) {r $t17=#$t17+1;.printf "Bitmap "}
.elsif( by(#$t0+a) == 8 ) {r $t16=#$t16+1;.printf "Pallete "}
.elsif( by(#$t0+a) == a ) {r $t15=#$t15+1;.printf "Font "}
.elsif( by(#$t0+a) == 10) {r $t14=#$t14+1;.printf "Brush "}
.elsif( by(#$t0+a) == 30) {r $t13=#$t13+1;.printf "Pen "}
.else {r $t12=#$t12+1;.printf "Unknown "}
.printf "%08x " , by(#$t0+b)
.printf "%08x\n" , dwo(#$t0+c)
r $t0 = #$t0+0x10
r $t2 = #$t2+1
}
}
r? #$t11 = ##c++(#$peb->ProcessParameters->ImagePathName.Buffer)
.printf /D "<b>Gdi Handles for %mu</b>\n", #$t11
.printf "Total Gdi Handles = %d\n", (#$t19+#$t18+#$t17+#$t16+#$t15+#$t14+#$t13+#$t12)
.printf "DC = %d\n" , #$t19 ; .printf "Font = %d\n" , #$t18
.printf "Region = %d\n" , #$t17 ; .printf "Brush = %d\n" , #$t16
.printf "Bitmap = %d\n" , #$t15 ; .printf "Pen = %d\n" , #$t14
.printf "Pallete = %d\n" , #$t13 ; .printf "Unknpown = %d\n" , #$t12
result of execution
0:000> $$>a< c:\wdscr\dumpgdi.txt
gdioffs Kaddr Pid Count Handle Type Tname ;IsLive UAddr
00472b30 fe6b5728 00000ca4 00000000 0d0102b3 00000001 DC 00000040 000e0cb0
00472be0 fdf73da8 00000ca4 00000000 420502be 00000005 Bitmap 00000040 00000000
004737b0 fddac108 00000ca4 00000000 9605037b 00000005 Bitmap 00000040 00000000
00474030 fe76eda8 00000ca4 00000000 eb050403 00000005 Bitmap 00000040 00000000
00474c90 fddde008 00000ca4 00000000 d70a04c9 0000000a Font 00000040 001fb1e8
0047ab80 fddab008 00000ca4 00000000 ba050ab8 00000005 Bitmap 00000040 00000000
0047f270 fddbcda8 00000ca4 00000000 16050f27 00000005 Bitmap 00000040 00000000
0047fef0 fdee4da8 00000ca4 00000000 cd050fef 00000005 Bitmap 00000040 00000000
004809f0 fe72eda8 00000ca4 00000000 3405109f 00000005 Bitmap 00000040 00000000
00480e50 fdda5aa8 00000ca4 00000000 0e0510e5 00000005 Bitmap 00000040 00000000
00481cf0 ffb0fda8 00000ca4 00000000 df0511cf 00000005 Bitmap 00000040 00000000
00481d70 fddb0da8 00000ca4 00000000 930511d7 00000005 Bitmap 00000040 00000000
00482020 ff4a1da8 00000ca4 00000000 d4051202 00000005 Bitmap 00000040 00000000
00482060 fddd4008 00000ca4 00000000 39051206 00000005 Bitmap 00000040 00000000
00482170 fddb6008 00000ca4 00000000 20051217 00000005 Bitmap 00000040 00000000
00483140 ff4a0008 00000ca4 00000000 4e051314 00000005 Bitmap 00000040 00000000
00483870 ff427980 00000ca4 00000000 6d051387 00000005 Bitmap 00000040 00000000
00483d80 fe7d04b0 00000ca4 00000000 bd0513d8 00000005 Bitmap 00000040 00000000
00484620 ff437eb8 00000ca4 00000000 0d101462 00000010 Brush 00000040 000f0fd8
004846a0 fddc2da8 00000ca4 00000000 d305146a 00000005 Bitmap 00000040 00000000
00484b80 fdf1a728 00000ca4 00000000 530114b8 00000001 DC 00000040 000e0ae0
Memory access error at ') != #$tpid) <-------- jumps out of catch block here
Gdi Handles for C:\Windows\system32\calc.exe
Total Gdi Handles = 21
DC = 2
Font = 0
Region = 17
Brush = 0
Bitmap = 1
Pen = 1
Pallete = 0
Unknpown = 0
From iPhone UIControl
UIControlEventAllTouchEvents = 0x00000FFF,
UIControlEventAllEditingEvents = 0x000F0000,
UIControlEventApplicationReserved = 0x0F000000,
UIControlEventSystemReserved = 0xF0000000,
UIControlEventAllEvents = 0xFFFFFFFF
Now I assume the UIControlEventApplication is the 'range' I can use to specify custom control events, but I have no idea how to do it properly. Only if I assign 0xF0000000 the control event will correctly fire. If I assign anything else (0xF0000001) the control event fires when it's not supposed to.
Some clarification:
enum {
UIBPMPickerControlEventBeginUpdate = 0x0F000000,
UIBPMPickerControlEventEndUpdate = // Which value do I use here?
};
My assumption of it being a range is based on the docs. Which say:
I assume this because the docs say: A range of control-event values available for application use.
Could anyone help me understand the type of enum declaration used in UIControl?
I would think 0x0F000000 is the 4 bits you have at your disposal for creating your own control events.
0x0F000000 = 00001111 00000000 00000000 00000000
So any combination of:
0x00000001<<27 = 00001000 00000000 00000000 00000000
0x00000001<<26 = 00000100 00000000 00000000 00000000
0x00000001<<25 = 00000010 00000000 00000000 00000000
0x00000001<<24 = 00000001 00000000 00000000 00000000
You can of course OR these together to create new ones:
0x00000001<<24 | 0x00000001<<25 = 00000011 00000000 00000000 00000000
So in your example:
enum {
UIBPMPickerControlEventBeginUpdate = 0x00000001<<24,
UIBPMPickerControlEventEndUpdate = 0x00000001<<25, ...
};
To use the enums you just do bitwise operations:
UIControlEventAllEditingEvents | UIControlEventApplicationReserved | UIControlEventApplicationReserved