Quantcast
Channel: IT Security Lab » hacking skype
Viewing all articles
Browse latest Browse all 3

Changed language does not persist when Skype is restarted: how to solve the annoying issue

$
0
0

You know, I like intelligent and handy software. I really do. But I hate with my all heart when the application (or the application's author?) is eee... "too smart". ;-) And what especially makes me nervous is when author calls some idiotic application's behavior "a  feature". I think Skype is a nice example of it. Look at this:

I have the default system language in Windows set up as English, but the default one for the non-Unicode programs is set to Polish. Nothing wrong with it, right. So when I start Skype for the first time it happily detects this setting and switches its language accordingly to the Polish too. Chaaarming. ;-)

Now let's imagine that I want to change the default Skype's language permanently to English (well, I much prefer English UI in all apps, ok). Seems life is easy: click the main menu, then Tools --> Change language --> English ... and the language is changed. Now try to close Skype and open it again... What you you see: the application's language is immediately switched back to Polish! Ok, you may try to attack the problem from the different side: Tools --> Options --> Tab: General setting --> Languages combo: English, then Save. Unfortunately the effect is exactly the same: when Skype is restarted - it switches the language to the one set up as the default for non-Unicode programs (in my case: Polish). God knows why this proggy has such amazing feature, but believe me - to change the language manually after each restart is becoming pretty annoying after some time.

As usual, I google the problem and quickly found out that I am not alone: look here for example http://portableapps.com/node/21644. So can we do anything? Yes we can®! :-)

I wrote a small program which runs the Skype and then simulates mouse clicks on the main menu and kind of "pseudo-manually" switches the application's language to the default one (English). This is also a nice small example how you may access the main menu of the application "B" from the code of application "A" and execute some  functionality in application "B". No worries, we are not "literally" moving the mouse cursor the the menu, but issuing some appropriate system messages - so everything is pretty elegant.

Ok, if someone needs only executables here they are (with the source code in Delphi):

Usage is very simple: extract the executable and put it to the same folder where your SkypePortable.exe or Skype.exe is located and then run. My little program runs Skype, waits until it is loaded and switches the language to English. Job done! :-)

Some technical background

Ok, so this is how it works. First of all we have to find the Skype window in the system (assure it exists, so we may get it's handle and access its child elements). This is rather trivial, so no need to explain anything. Once the window is found this is what we are doing:

var
  menu: HMenu;
  id: integer;
  s: Array[0..255] of char;
begin
  tmrMain.Enabled := false;

  h := findWindow(pchar('tSkMainForm.UnicodeClass'), nil);  //--- find Skype's window
  menu := getMenu(h); //--- find the main menu
  GetMenuString(menu, 5, @s[0], 255, MF_BYPOSITION); //--- get the text of 6th menu item (should be '&Help')

  if string(s) <> '&Help' then  //--- current language is NOT English
  begin
    menu := getMenu(h); //--- main menu
    menu := GetSubMenu(menu, 4); //--- find the 5th menu item

    //--- activate this (5th) menu item, so all subitems can be redrawn. This is IMPORTANT!
    SendMessage(h, WM_INITMENU, WPARAM(menu), 0);
    SendMessage(h, WM_INITMENUPOPUP, WPARAM(menu),0);

    menu := GetSubMenu(menu, 2); //--- find the 3rd submenu item

    id := GetMenuItemID(menu, 9); //--- 10th menu item (select "English")
    PostMessage(h, WM_COMMAND, id, 0); //--- click it! :-)
  end;

  SendMessage(h, WM_SYSCOMMAND, SC_MINIMIZE, 0);
  application.Terminate;
end;

So 1st thing we have to do - we have to check what language is set up currently. We are getting the text of the 6th menu item and checking if it is equal to "&Help" or not. Currently it's "&Pomoc", which means the current language is not English (yea, it's Polish actually).

This is the code used for checking:

  h := findWindow(pchar('tSkMainForm.UnicodeClass'), nil);  //--- find Skype's window
  menu := getMenu(h); //--- find the main menu
  GetMenuString(menu, 5, @s[0], 255, MF_BYPOSITION); //--- get the text of 6th menu item (should be '&Help')

  if string(s) <> '&Help' then  //--- current language is NOT English
  begin
  [...]
  end;

Now we have to iterate through the menus and sub-menus and run some action on the target item. Look at this code:

    menu := getMenu(h); //--- main menu
    menu := GetSubMenu(menu, 4); //--- find the 5th menu item

    //--- activate this (5th) menu item, so all subitems can be redrawn. This is IMPORTANT!
    SendMessage(h, WM_INITMENU, WPARAM(menu), 0);
    SendMessage(h, WM_INITMENUPOPUP, WPARAM(menu),0);

    menu := GetSubMenu(menu, 2); //--- find the 3rd submenu item

    id := GetMenuItemID(menu, 9); //--- 10th menu item (select "English")
    PostMessage(h, WM_COMMAND, id, 0); //--- click it! :-)

Important detail: look at strings highlighted in red: this is important element of the code as the sub-menu with the list of languages is generated "on-the-fly" once the parent menu item is activated. Without it: the 10th menu item (language "English") simply does not exist, (hence can't be called).

One more remark: the proposed solution requires Skype user interface (Visual Style of the window) get running in "Classic Windows" mode.


Viewing all articles
Browse latest Browse all 3

Latest Images

Trending Articles





Latest Images