📜 ⬆️ ⬇️

Disassemble Windows Explorer - disable grouping on the taskbar

One day, in 2009, Windows 7 came out. At that time I was sitting on Vista, which slowed down on my old computer, and I decided to transfer to the seven right after it was released.

The first thing I noticed after installation is the new taskbar. More specifically, the fact that it groups the buttons according to the program to which they belong.


')
Immediately I got into the settings to disable this disgrace, and was surprised to find that the group is not turned off. The closest option to the desired, Never Combine, still groups the buttons.



I thought that, like me, many people would not like it, and I was sure that a week or two later a solution to this problem would come up on the Internet. But I did not find anything worthwhile, and I realized that I would have to act on my own.

Under the cut:

Getting started


To understand the process described below, it is advisable to have a basic knowledge of the assembler.

In order to wean the taskbar from grouping, we need OllyDbg , a free, proprietary 32-bit assembler-level debugger for Windows operating systems, designed to analyze and modify compiled executable files and libraries operating in user mode (ring-3) © Wikipedia .

You can repeat the process on Windows 7 or Windows 8. Unfortunately, at the moment there is only a 32-bit version of OllyDbg, so if you have a 64-bit OS, you will not be able to repeat the following steps (in this case you can use a virtual machine ).

Installation OllyDbg

OllyDbg is a portable program and does not need installation. Create a folder with write permissions, and copy files from this archive there .

Configure Microsoft Symbol Server

Microsoft Symbol Server - Microsoft's debugging symbols server, thanks to which we, in addition to the pure assembler, will also see the names of functions and variables. This is very helpful in analyzing the code.

To do this, do the following:

Joining the explorer process

As you know, the taskbar is part of the Windows Explorer process. Run OllyDbg, and select File -> Attach .... Then, select the explorer and click on Attach .
Screenshots


Attach, from English - to attach - that is, we attach our debugger to the conductor to debug it.

Then we wait until all modules are loaded. This may take several minutes, and at this time the conductor will not respond. After the download is completed, Paused will be written on the yellow background in the status bar on the right - that is, the process is suspended. Click F9 to resume the process.

Attention, exceptions : if the process pauses and Exception xxxxxxxx appears on the status bar (as in the screenshot below), press Shift + F9 to send the exception to its intended purpose.
Screenshot

Overview of Explorer Functions

Now the conductor is working under the supervision of our debugger, OllyDbg. If the connection to the server debugging characters passed as it should, we can look at the functions of the explorer.

First, open the explorer process module in the CPU window of the debugger. To do this, open the modules window (the letter E on a blue background), right-click on Explorer , and select View code in CPU .
Screenshot

Then, right click on the code and select Search for -> Names . Before us will be a list of functions that are present in the explorer. For more convenient work with the list, sort it by name, copy it and paste it into the text into your favorite text editor.
Screenshots


So, we need to disable grouping. It is logical to start the search with the word group. Two classes immediately strike the eye: CTaskBtnGroup and CTaskGroup . Together, these two classes have 131 functions — not very much for a quick look at the titles.

It’s hard for me to say if we can find the function we need by just learning the names, since I’m already well acquainted with many of them. In any case, the function we need - CTaskGroup :: DoesWindowMatch , the name of which translates to whether the window matches , and it does exactly that - answers whether the window is suitable for a specific group.
Screenshot

View selected function

We found a function with an interesting name, now let's see what it is. Let's go back to OllyDbg, press Ctrl + G and go to the address of the function (that eight-digit number at the beginning of the line, in our case 00973629).

PS I advise you to turn on the highlight of Jumps and calls , thanks to which function calls and conditional / unconditional jumps are clearly visible.
Screenshot

So, here is our function:


Columns, from left to right: address, bytes, commands (assembler), comments.
Functions are marked in blue, transitions in yellow. We will focus on them.

First of all, some function is called, and a transition occurs depending on the result. Here I will not linger on them, I will only note that they have nothing to do with our task.

Then we see three transitions. The first one jumps over the second and third. The second and third go somewhere far away - let's see where ...

The first
The WinAPI function ILIsEqual , which compares two structures, is immediately apparent. After some analysis, it becomes clear that the compared structures are associated with groups. Our goal is to cancel any grouping, so we patch the code so that the conductor thinks that the structures are not equal.



To do this, we write an unconditional jump JMP, as in the screenshot above.

Second
As in the first time, immediately see the WinAPI function for comparison, this time the text - CompareStringOrdinal . Again, after experimenting it becomes clear that this comparison is also related to groups. This time, the so-called Application ID is compared - the application ID, according to which the taskbar groups the buttons.



Again, we set an unconditional jump, forcing the conductor to think that all identifiers are different.

We try

The big advantage of the debugger from, for example, a simple disassembler is that the changes take effect immediately, since we modify the memory of the running process directly. For the same reason, you need to be very careful, as an error can lead to the collapse of the process.

Let's try to open several copies of the notebook, and see that they are not grouped together:



Happened :)

Since we changed the code only in the memory of the running process, our modification will last only until the completion of the process.

Bonus - decompiled version of the CTaskGroup function :: DoesWindowMatch

In spite of the fact that the original language of this code is C ++, the samopisny decompilation on pure C is shown below.

/* return: S_OK if there's a match, E_FAIL otherwise *pnMatch: 1: AppId matches, ITEMIDLIST is missing 2: AppId matches, ITEMIDLIST doesn't match 3: ITEMIDLIST matches 4: hWnd already exists (pTaskItem recieves the CTaskItem) */ HRESULT CTaskGroup_DoesWindowMatch(void /*CTaskGroup*/ *this, /*IN*/ HWND hCompareWnd, /*IN*/ ITEMIDLIST *pCompareItemIdList, /*IN*/ WCHAR *pCompareAppId, /*OUT*/ int *pnMatch, /*OUT*/ void /*CTaskItem*/ **pTaskItem) { void /*CTaskItem*/ *CompareWndTaskItem; int nMatch; HRESULT hr; nMatch = 0; hr = this->lpVtbl->GetItemFromWindow(this, hCompareWnd, &CompareWndTaskItem); if(SUCCEEDED(hr)) // if an item for this window already exists { if(pTaskItem) { *pTaskItem = NULL; IUnknown_Set(pTaskItem, CompareWndTaskItem); } nMatch = 4; CompareWndTaskItem->lpVtbl->Release(CompareWndTaskItem); } else { if(!(this->SomeFlags & 0x80000000)) { if(pCompareItemIdList && this->pItemIdList && ILIsEqual(pCompareItemIdList, this->pItemIdList) != 0) { nMatch = 3; hr = S_OK; } else if(pCompareAppId && CompareStringOrdinal(this->pAppId, -1, pCompareAppId, -1, TRUE) == CSTR_EQUAL) { hr = S_OK; if(pCompareItemIdList && this->pItemIdList) nMatch = 2; else nMatch = 1; } } } *pnMatch = nMatch; return hr; } 


Turnkey solution


The 7+ Taskbar Tweaker program, authored by me, is able to disable grouping both globally and selectively by the Application ID. In addition, there are in the presence of several interesting settings on the taskbar.



Conclusion


Sometimes I open an article on a habr that seems interesting to me, but after I start reading, I understand that it is not that interesting (or not very clear). In such cases, I often immediately turn down to the conclusion / conclusions.

If you are here for the same reason, I will tell you briefly what was discussed:
I took the debugger, and attached it to the conductor. Then I found the necessary function, and changed it so that the conductor would think that any window created would not fit into any of the existing groups. Due to this change, Explorer has stopped grouping buttons on the taskbar.

Source: https://habr.com/ru/post/174593/


All Articles