← Back to DevelopmentAging & Mixing viewer.dll generatorProgramsClan filesInternet Information ServiceOllyDbg tutorialsMiscellaneousSkinsLinks / Files

fix_client_area_size

← Back to Miscellaneous
PT is poorly coded. Nothing knew.
When the game window is created, the resolution you selected is set to the entire window, not to the inside of the window, as it's supposed to be.

This, among other things, prevents you from reaching the bottom of the screen with your cursor in windowed mode.
Let's fix it.

1. So what's up ?
When you select a resolution of, let's say, 1024x768, you expect to have this :

01.png

In fullscreen mode, it's all good because your window takes the whole screen, has no border, no title bar, just the inside.
But in windowed mode, things are a bit different :

02.png

Yep. The function you use to create the window is called CreateWindowEx. Among other parameters, you give it your window height and width.
As said in the introduction, this is the entire window size. This cause the inside of the window to be smaller than expected.

2. AdjustWindowRectEx
Luckily, there's a function to fix that. It's called AdjustWindowRectEx.

To that function, you pass a structure named RECT. It contains 4 DWORD values : left, top, right, bottom.
Basically, left and right are coordinates on the x axis, and top and right are on the y axis.

03.png

In our code, top and left will be set to 0. Right will be the window's width, and Bottom the window's height.
Depending on the coordinates, and the styles you give to it, it computes new coordinates.
Those coordinates allow you to calculate the real size of the window.

04.png

The red rectangle is the new coordinates. It's the real window size we have to pass to CreateWindowEx.
As you can see :
* Top value decreased (it's now negative
* Left value decreased (it's now negative)
* Right value increased
* Bottom value increased

But it's not over, we need to calculate the new height and width. It's quite easy :
* Height = Bottom - Top (Top being negative, it'll be added)
* Width = Right - Left (same here)

3. Importing AdjustWindowRectEx
That function lives in USER32.dll. Our first problem is that it's not imported by the game. We need to change that.
First open your client with CFF Explorer :

05.jpg

Click on Import Adder :

06.jpg

Then click Add, and add the USER32.dll (it should be located in C:\Windows\system32) :

07.jpg

In the list of Exported function, click AdjustWindowRectEx and press Import by name :

08.jpg

Check Create new section and click Rebuild Import Table :

09.jpg

Now go to the Section Header and rename the new section (called .newIT) to something sexier :P (I'll call mine .iadjust) :

10.jpg

While you're at it, you can also create a new section for the new code. Make sure it's Executable and Writable (i know it's bad, but it's just for 1 execution at startup).
1000 h should be more than enough (it would fit in ALOT less :D) for the new code. I'll call mine .cadjust :

* Right-click and Add section (empty data) :

11.jpg

* 1000 h :

12.jpg

* Flags (Right-click and Change section flags) :

13.jpg

* Rename :

14.jpg

Finally save your file.

3. Locating the pointer to AdjustWindowRectEx
Now that the function is being imported, we need to locate its pointer to call it.

Open your client with OllyDbg, and open one of the client section (in the memory (M) window) (here I opened the PE header) :

15.jpg

Search names (Right click > Search for > Names or Ctrl + N) :

16.jpg

Sort the results by Name, scroll down a bit and you should find the function :

17.jpg

You can either keep the window opened, or do Right-click > Copy to clipboard > Address and save the address somewhere. That's what we were looking for.

4. New code
If you read the paper about windowed mode maximized, you know where the window is created.
The offset is 004166AB.

OllyDbg - Client Side

0041667D      53            PUSH EBX                                            ;  lParam
0041667E      57            PUSH EDI                                            ;  hInst
0041667F      53            PUSH EBX                                            ;  hMenu
00416680      53            PUSH EBX                                            ;  hParent
00416681      55            PUSH EBP                                            ;  Height
00416682      56            PUSH ESI                                            ;  Width
00416683      8B35 ACA25B00 MOV ESI,DWORD PTR DS:[<&USER32.CreateWindowExA>]    ;
00416689      68 00000080   PUSH 80000000                                       ;  Y = CW_USEDEFAULT
0041668E      3BC3          CMP EAX,EBX                                         ;
00416690      A1 28DA5E00   MOV EAX,DWORD PTR DS:[5EDA28]                       ;  ASCII "SGPT PRISTONTALE CLIENT 1873------Thanks Sandurr^^"
00416695      68 00000080   PUSH 80000000                                       ;  X = CW_USEDEFAULT
0041669A      74 07         JE SHORT 004166A3                                   ;
0041669C      68 0800CF80   PUSH 80CF0008                                       ;
004166A1      EB 05         JMP SHORT 004166A8                                  ;
004166A3      68 08000090   PUSH 90000008                                       ;
004166A8      50            PUSH EAX                                            ;  WindowName => "SGPT PRISTONTALE CLIENT 1873------Thanks Sandurr^^"
004166A9      50            PUSH EAX                                            ;  ClassName => "SGPT PRISTONTALE CLIENT 1873------Thanks Sandurr^^"
004166AA      53            PUSH EBX                                            ;  ExtStyle
004166AB      FFD6          CALL ESI                                            ;  USER32.CreateWindowExA


As usual, there's no space for extra code, but this time the instruction before this one, is the size of a JMP.

OllyDbg - Client Side

00416678      A1 24115F00   MOV EAX,DWORD PTR DS:[5F1124]

We won't have alot of code to move.

Let's go to our newly created section and add the new code !
I'm going to leave the first 4 DWORDs empty. They will be used to store the RECT structure. (Plus another extra 4 for readability) :

OllyDbg - Client Side

0450F000  00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
0450F010  00 00 00 00|00 00 00 00|00 00 00 00|00 00 00 00| ................
0450F020  00                                               .


I'll start at 0450F020.
Just read the comments to understand what it does. PointerToAdjustWindowRecEx is the address we saved earlier.

OllyDbg - Client Side

0450F020    A1 24115F00                 MOV EAX,DWORD PTR DS:[5F1124]                          ; The instruction we replaced with a JMP
0450F025    53                          PUSH EBX                                               ; Fourth argument : ExtStyle (EBX, the same as CreateWindowEx)
0450F026    6A 00                       PUSH 0                                                 ; Third argument : Menu (none)
0450F028    39D8                        CMP EAX,EBX                                            ; Second argument : Fullscreen/windowed styles (Taken from CreateWindowEx)
0450F02A    74 05                       JE SHORT 0450F031
0450F02C    68 0800CF80                 PUSH 80CF0008
0450F031    EB 05                       JMP SHORT 0450F038
0450F033    68 08000090                 PUSH 90000008                                          ; End of fullscreen/windowed styles
0450F038    68 00F05004                 PUSH OFFSET 0450F000                                   ; First argument : RECT structure (the 4 DWORDs we left empty)
0450F03D    C705 00F05004 00000000      MOV DWORD PTR DS:[450F000],0                           ; Manually setting LEFT to 0
0450F047    C705 04F05004 00000000      MOV DWORD PTR DS:[450F004],0                           ; Manually setting TOP to 0
0450F051    8935 08F05004               MOV DWORD PTR DS:[450F008],ESI                         ; Manually setting RIGHT to ESI (that's where the width is stored)
0450F057    892D 0CF05004               MOV DWORD PTR DS:[450F00C],EBP                         ; Manually setting BOTTOM to EBP (that's where the height is stored)
0450F05D    FF15 60E15004               CALL DWORD PTR DS:[<&user32.AdjustWindowRectEx>]       ; CALL DWORD PTR DS:[PointerToAdjustWindowRecEx]
0450F063    8B35 08F05004               MOV ESI,DWORD PTR DS:[450F008]                         ; Moving RIGHT to ESI (the width)
0450F069    2B35 00F05004               SUB ESI,DWORD PTR DS:[450F000]                         ; Substracting LEFT to RIGHT to calculate the new width
0450F06F    8B2D 0CF05004               MOV EBP,DWORD PTR DS:[450F00C]                         ; Moving BOTTOM to EBP (the height)
0450F075    2B2D 04F05004               SUB EBP,DWORD PTR DS:[450F004]                         ; Substracting TOP to BOTTOM to calculate the new height
0450F07B    E9 FD75F0FB                 JMP 0041667D                                           ; We calculated the new width and height, we go back


You also need to make the client jump to that new code :

OllyDbg - Client Side

00416678      E9 A3890F04   JMP 0450F020


You can now reach the buttons you couldn't reach before in windowed mode :)

18.jpg

5. Don't apply to fullscreen mode
It's quite easy you just need to make it jump over the AdjustWindowRectEx call when it's fullscreen mode.

OllyDbg - Client Side

0450F020   \A1 24115F00                 MOV EAX,DWORD PTR DS:[5F1124]
0450F025    39D8                        CMP EAX,EBX
0450F027    74 4B                       JE SHORT 0450F074
0450F029    53                          PUSH EBX
0450F02A    6A 00                       PUSH 0
0450F02C    68 0800CF80                 PUSH 80CF0008
0450F031    68 00F05004                 PUSH OFFSET 0450F000
0450F036    C705 00F05004 00000000      MOV DWORD PTR DS:[450F000],0
0450F040    C705 04F05004 00000000      MOV DWORD PTR DS:[450F004],0
0450F04A    8935 08F05004               MOV DWORD PTR DS:[450F008],ESI
0450F050    892D 0CF05004               MOV DWORD PTR DS:[450F00C],EBP
0450F056    FF15 60E15004               CALL DWORD PTR DS:[<&user32.AdjustWindowRectEx>]
0450F05C    8B35 08F05004               MOV ESI,DWORD PTR DS:[450F008]
0450F062    2B35 00F05004               SUB ESI,DWORD PTR DS:[450F000]
0450F068    8B2D 0CF05004               MOV EBP,DWORD PTR DS:[450F00C]
0450F06E    2B2D 04F05004               SUB EBP,DWORD PTR DS:[450F004]
0450F074  ^ E9 0476F0FB                 JMP 0041667D