Up until a few years ago, I was a huge OS optimization junkie, but thankfully the level of obsession has gone down in recent years. I still remember the time when a friend had come over to exchange some data and we spent almost an hour trying to get the bloody network sharing to work in XP. As it happened I was in my 'no open ports' OCD stage and I had "fixed" Windows so that no TCP/IP ports were left open. Apparently that involved neutering netbt/netbios and other networking components to the point where getting them back was a chore. I can't remember but I think we ended up setting up an FTP server.
So, the new me, doesn't care too much about crap that runs on system startup or the terrible service-bloat that the popular malware iTunes forces on you just to copy a mp3 file to a fucking flash drive. Ofcource, I also do realize that many of the Windows optimization tips are just snake-oil and there won't be a perceptible difference in OS performance (or at least, one that justifies all the time wasted troubleshooting problems caused by your b0rked system state). Anyway, I recently moved up to Win7 from Vista and as I was installing my mouse (Razer Diamondback 3G) driver, my dormant OCD stirred from its deep slumber and messed with my head.
I realized I wasn't really using the config tool for any purpose other than to set my mouse's CPI to 800 instead of the native 1800 and that I ought to get rid of it. Ofcource as it turned out the mouse doesn't even have any internal memory to save this setting and that the mouse config tool, on system startup, sets the dpi to 800.
After poking around it seemed like the tool was functionally separated into 4 main binaries : razerhid.exe, razertra.exe, razercfg.exe, razerofa.exe. Just by looking at the naming I guessed that the razercfg.exe was the config tool itself, the razertra.exe was the system taskbar (tray) tool and the razerofa.exe was the on-the-fly sensitivity tool. I didn't quite know whatrazerhid.exe was but I just guessed it was something to do with USB HID class devices. The process hierarchy had razerhid.exe as the parent process, with razertra.exe and razerofa.exe as child processes. And razercfg.exe was the child process of razertra.exe
Now, I just had to find out where the settings were stored, and how specific commands were sent to the mouse to change the CPI. The registry was the first guess so I ran a registry monitor to get the location of the settings. So, now I knew that the settings were stored at HKCU\Control Panel\Mouse\razer\* and the one I was primarily interested in was called Dpi1600Enable. I now needed to find out which of these binaries was actually sending the command to the device driver. I fired up IDA and went rummaging through the imports table and possible LoadLibrary/GetProcAdress calls in razercfg.exe and razerhid.exe to see if I could find anything of interest. For some reason trying to debug and trace through razerhid.exe caused random bluescreens with the mouse driver. I didn't want to spend time tracking that down, so I slapped on KD and hooked up my laptop through 1394 and used a mixture of static analysis with IDA and live debugging with KD to get an idea of what was happening.
After some more poking around, one thing seemed fairly certain. razercfg.exe wasn't responsible for actually programming the mouse's driver and only seemed to deal with registry keys. I now concentrated all my efforts on razerhid.exe as it had the delicious kernel32!DeviceIoControl import that was probably doing all the dirty work of programming the mouse. After considerable debugging and tracing through the god-awful MFC disassembly I hit upon a function that was possibly performing the actual device programming.
; comments describe the function that the call points to.
.text:004031B0 sub_4031B0 proc near
.text:004031B0
.text:004031B0 push esi
.text:004031B1 mov esi, ecx
.text:004031B3 call sub_402DA0 ; 4 DeviceIoControl calls that use contents of the
sensitivity settings from the registry
.text:004031B8 mov ecx, esi
.text:004031BA call sub_402D30 ; a couple of calls to DeviceIoControl
.text:004031BF mov ecx, esi
.text:004031C1 call sub_402EC0 ; call to SetDoubleClickTime
.text:004031C6 mov ecx, esi
.text:004031C8 call sub_402ED0 ; call to DeviceIoControl, SystemParametersInfoA,
SwapMouseButton
.text:004031CD mov ecx, esi
.text:004031CF call sub_402F70 ; calls to SystemParametersInfo and RegQueryValueEx
.text:004031D4 mov ecx, esi
.text:004031D6 call sub_403110 ; calls to SystemParametersInfo
.text:004031DB pop esi
.text:004031DC retn
.text:004031DC sub_4031B0 endp
After some more boring debugging and live execution manipulation, it seemed like sub_402D30 was the most likely candidate. Time to test it out by writing a simple program to duplicate the function sub_402D30.
; comments are IDA generated .text:00402D30 sub_402D30 proc near ; CODE XREF: sub_4031B0+A .text:00402D30 mov eax, hDevice .text:00402D35 push ebx .text:00402D36 push edi .text:00402D37 mov edi, ecx .text:00402D39 test eax, eax .text:00402D3B jz short loc_402D97 .text:00402D3D mov ecx, [edi+0E20h] .text:00402D43 xor ebx, ebx .text:00402D45 test ecx, ecx .text:00402D47 jle short loc_402D97 .text:00402D49 push ebp .text:00402D4A mov ebp, ds:Sleep .text:00402D50 push esi .text:00402D51 mov esi, ds:DeviceIoControl .text:00402D57 jmp short loc_402D5E .text:00402D59 ; --------------------------------------------------------------------------- .text:00402D59 .text:00402D59 loc_402D59: ; CODE XREF: sub_402D30+63 .text:00402D59 mov eax, hDevice .text:00402D5E .text:00402D5E loc_402D5E: ; CODE XREF: sub_402D30+27 .text:00402D5E mov ecx, [edi+778h] .text:00402D64 push 0 ; lpOverlapped .text:00402D66 push offset BytesReturned ; lpBytesReturned .text:00402D6B push 0 ; nOutBufferSize .text:00402D6D push 0 ; lpOutBuffer .text:00402D6F push 0 ; nInBufferSize .text:00402D71 test ecx, ecx .text:00402D73 push 0 ; lpInBuffer .text:00402D75 jz short loc_402D7E .text:00402D77 push 22244Ch .text:00402D7C jmp short loc_402D83 .text:00402D7E ; --------------------------------------------------------------------------- .text:00402D7E .text:00402D7E loc_402D7E: ; CODE XREF: sub_402D30+45 .text:00402D7E push 222450h ; dwIoControlCode .text:00402D83 .text:00402D83 loc_402D83: ; CODE XREF: sub_402D30+4C .text:00402D83 push eax ; hDevice .text:00402D84 call esi ; DeviceIoControl .text:00402D86 push 0Ah ; dwMilliseconds .text:00402D88 call ebp ; Sleep .text:00402D8A mov eax, [edi+0E20h] .text:00402D90 inc ebx .text:00402D91 cmp ebx, eax .text:00402D93 jl short loc_402D59 .text:00402D95 pop esi .text:00402D96 pop ebp .text:00402D97 .text:00402D97 loc_402D97: ; CODE XREF: sub_402D30+B .text:00402D97 ; sub_402D30+17 .text:00402D97 pop edi .text:00402D98 pop ebx .text:00402D99 retn .text:00402D99 sub_402D30 endp
Bingo ! Simply sending the control code 222450h set the device to 800CPI mode and sending 22244Ch set it to 1800CPI. Finally, I can now save a combined working set of about 20 megs from occupying physical memory ! I won't necessarily notice it in my 8GB mem bucket, but hey, the OCD seems to have died off. I can sleep peacefully now.
Download:
Sample code to set DPI:
set800.cpp
set1800.cpp
Note: I've merely put these files up here for entertainment purposes. Using these might mess with razers config tool. To make this code more robust you need to add some calls to set a few registry keys, investigate what the proper practice is when using DeviceIOControl, etc (Whether you need to confirm that the device has been correctly programmed, Whether delays are needed in around DeviceIOControl calls, Whether all error conditions are handled etc)
}