28th September was a sunny and amazing day for us, the open source lovers. During the whole day, the Universidade Nova de Lisboa held the #OpenSourceLx event. The biggest and free open source event in Portugal.
Projects and companies as Syone, RedHat, Microsoft, Elastic, FSF, IpBrick, among others, were offering simultaneous talks during the event. In this edition I was invited to talk about the ReactOS project evolution during 45 minutes in the “ReactOS: the open source Windows clone” as the Chief Strategy and Technology Officer of ReactOS.
The OpenSourceLX event.
Organizers of the event were really amazing guys. Do you know that feeling when you step into an open source event and you immediately notice the organizers do *really* believe in open source? #OpenSourceLx is one of those. They don’t try to impress you with tons of commercial activities but they do really select useful and informative talks. Sadly, and as a personal note, some of other open source events are commercially derailing themselves after some editions (I can name a few) just to make money around the “open source” buzz word. This is not the case, and OpenSourceLisbon has been around for 15th Editions.
So after enjoying their Talks, it was time of the ReactOS one.
During the “ReactOS: The open source Windows clone”, I tried to highlight why ReactOS is attracting newcomers daily, why just replacing a Windows operating system with another Windows-alike os is the proper way to reduce migration risks, and how slowly (but steady) more companies and final clients are knocking ReactOS doors. And stepped into the ReactOS architecture just to show how ReactOS mimics/clones the Windows one in order to ensure the maximum compatibility in the medium and long term.
The Woah! effect
After finishing the talk, Demo time started. Or maybe it did not? As soon as I minimized the full screen PDF presentation it was revealed that during those 45 minutes the talk was done using ReactOS and not any other OS. Even more, the PDF was executed on Acrobat Reader X. Choosing Acrobat was not a coincidence, to begin with it doesn’t have a Gnu-Linux version (so no one could think ReactOS is a Linux distro “dressed” as Windows) and also it is a complex software to show ReactOS nowadays capabilities.
As soon as the people in the talk realized it was ReactOS, the “Woah!” and murmurings started to happen, mixed with a flow of questions. It was a really pleasure to show the amazing progress the ReactOS team has been doing lately, and revealing an exclusive: ReactOS was going to migrate to GitHub on 3rd October after 20 years using SVN.
The Lisbon City
You know I can’t help to take some pics from the cities I’m invited to give a talk. So for those not knowing how awesome Lisbon is…just a couple of pics…
Again, and in the name of the ReactOS Foundation, I want to thank this amazing opportunity for ReactOS (It was our first time ever in Portugal!) with special kudos to all the volunteers and the organization staff I had the opportunity to talk.
A wonderful experience!
This year ReactOS has been selected to be shown in one of the most important Free and Open source events in Germany: FrOSCon. It’s our first time there but their program is impressive. Colin Finck, Mark Jansen, Giannis Adamopoulos, and me will be present to show our latest achievements in the ReactOS booth….
The event takes place on 19th and 20th August (weekend, btw) so feel free to book your flights or plan a nice weekend to meet us there. Surroundings are wonderful (if you need an extra excuse *cough*).
Even more, this year we’ve decided to strategically place the ReactOS Hackfest the week before FrOSCon.
Crazy? Probably. But FrOSCon will become, this way, an extra-motivation. You know “We can’t fail, thousands of visitors are willing to see our Hackfest results”. The ReactOS Hackfest is just a coding, but overall, a fun week. A week where selected developers will work in some critical tasks in a relaxed environment, out of the offices. For such the ReactOS Foundation has rented a nice loft in the center of Cologne. The ReactOS Hackfest is closed to public but we’ll be live streaming at the end of the day summing up our achievements and facepalms. Feel free to join them. You know we love interaction. Keep following the ReactOS or my twitter account to know our daily schedule.
Some critical goals we’ll address as a team are: discussing how to properly move from SVN to GIT(once and for all), test our new USB driver stack with tons of USB pieces of hardware, fix Chrome’s sandbox mode, finish the new and online ReactOS Apps Manager, just among others.
This time we won’t be using Scrum during the Hackfest. How so?.
Muahaha…This time we will be using the new and awesome agile method called: ScrumBeer 2.0. Well, if you feel 1337 enough you can use its real name, ScrumB33r. Of course there are 2 different flavors: With alcohol and without it.
It’s just slightly different to the typical Scrum one, but it seems to work pretty well in Hackfests. Not kidding. I’m just writing a new post about what this crazy “ScrumB33r” agile method is about.
Probably one of the worst false friends out there is the amazing Wcsncpy and all its family. Each time I see code using (and abusing) of wcsncpy a cold fear run through my whole back. Believe me, run away from it and all its family: wcsncpy(the father), strncpy(the mather), and all its sons. Whenever possible.
The worst part of wcsncpy is that it acts as one of those worst friends who are BSing in your back and you’re not noticing at all, until you begin discovering odd behaviors in your code. Even more, wcsncpy is such an amazing false friend that it probably won’t show bugs in the lines of code where it comfortly lives but, when (often) misused, will throw random bugged behaviors in any part of your program.
This wcsncpy family was sold at its time as the evolution of the wcscpy one. Did you notice the missing “n”?
The “non-n” Wcspcy, strcpy, and all its sons were letting you to copy a C string pointed by source into the array pointed by destination. However this “non-n” family were soon the main responsibles of tons of buffer overflows. This “non-n” family is blindly (stubbornish) copying from destination to source without caring at all to stop when the destination buffer is full. So if the destination array is smaller than the source array, or if you forget to end your source array with a string terminator, you will end corrupting memory sit next to your destination array memory addresses. And these cases were happening zillion of times.
wcscpy (wchar_t* destination, const wchar_t* source);
You can see how wcscpy was receiving just the start address of source and destination as params so it doesn’t have a way to know when it is overflowing the destination array. It just stops copying when it finds the Null terminator in the source buffer (good luck if you forgot to append to it)
So if the problem is that the function doesn’t know when to stop, why not creating a family of functions which receives an extra param “n
-um” telling how many characters must be written to the destination buffer? Wow! Amazing idea! So the wcsncpy family was created.
wcsncpy (wchar_t* destination, const wchar_t* source, size_t num);
And then Developers were starting to feel safer! Long life to Wcsncpy(they said)! It’s our savor!
You can see in tons of threads recommending you to use the “n” family because it is much safer than the “non-n” one.
Then why? Why this “n” family was introducing much more corruptions?
First because the “non-n” one was pretty well-known to be an overflow lover so each time it was being used, developers were being really cautious and double checking. However when they started to use the “n” family they got much more relaxed, believing in the new “num” param as their own Super-num-an, but it was in a galaxy far-far away from that.
On the other hand Num was, and is, totally misinterpreted by developers.
Some thought that it was the maximum Num-ber of characters to be copied from source to destiny believing also that “wcsncpy” will stop when the destination buffer is full (magically maybe?). But nope, NUM is the Number of characters to be copied (ignoring the length of the source and destiny). And the stubborn “n” function will really copy NUM characters to destination, even if that means overflowing it. Next line, used by these kind of developers, will corrupt memory by overflowing destination, if destination is a 20 wchar array.
wcsncpy (destination, source, MAX_PATH);
Let me highlight one hipercommun pitfall. The old “non-n” family was using the Null terminator of the source string to STOP copying. So when the “n” family was introduced a lot of devs thought that the “num” param was explicitly defining the number of characters BUT that if the Null terminator was found before copying such “num” characters the function will inmediatly stop copying there. Not the case of the “n-family”.
Some others thought that the Num param was the size of the destination but in bytes. So if destination is a 20 wchar array the following line will corrupt their memory due overflow ( sizeo(WCHAR) * 20 = 40): .
wcsncpy (destination, source, sizeof(WCHAR) * 20);
Sometimes the corruption is even more difficult to track, something like:
wcsncpy (destination, source, SOURCESIZE);
Here it is pretty obvious, but if you name the variable SOURCESIZE as SIZE, you will have a nice corruption in front of your eyes (if source is bigger than destination), and you not noticing it at all.
And finally, copypasta, since the name is tedious to write, and there are 3 params being received copy and pasting is a new way to introduce bugs.
wcsncpy (destination, source, numdestination); wcsncpy (destination2, source2, numdestination); wcsncpy (destination3, source3, numdestination);
Oops, he forgot to modify the last param. Potential overflows there.
This patch I made for ReactOS shows you how easy you can fall in the trap, when the num param (Usize) is being calculated in the parent function and then thrown to the helper function. Our Coverity scans were an amazing help to find this flaw.
So if you used this lovely function, please check twice. Your non-corrupted memory deserves it 😉
Criticism, after being filtered, becomes an amazing way to develop and measure our work or strategies. Even more, strategy without criticism is not a strategy. External criticism should be part of our daily strategy work and it is presented in many ways..
What a KPI is? Just an objective criticism of your current applied strategy.
What about our users’ feedback? Just a cooler & softer word than the criticism word but, after all, the same thing.
So your work and strategy is going to be criticized. Directly or through its final results. At your face or at your back. Learning to filter out criticisms correctly is key to separate noisy ones from the valuable ones..
What a criticism is?. How many types do exist?
If you’d have asked me this question several years ago, I’d answer, off the top of my head, just two. Those that “I do like” and those that “I do not like at all”. The first are usually called “positive criticisms”, and the latter ones are called “negative criticisms”.
Ask this same question to your relatives or friends. Most of them will answer you in the same way. It’s a social issue. Probably a dysfunction in the educational system. And, no doubts, a big issue in team working.
I prefer, however, to distinguish 4 different kind of criticisms. You can view them in the next picture.
I’ll try to explain the four of them by using the same example. This time John is going to be criticized.
Positive constructive criticism .
“John, I loved your presentation. Adding the comparative and showing our strong points in the last slide have been an excellent idea”.
This kind of criticism shares a positive message but also a constructive one since you’re explaining why you liked it. Unfortunately it is a criticism in danger of extinction.
Recognizing John’s effort doesn’t just motivate him, but shows him the correct way. All-in-one
.A really nice example of positive constructed criticisms are KPIs. A KPI showing an improving trend, can be understood as a positive criticism but, best of all, it is also a constructive one since KPIs are objective.
Negative constructive criticism
” John, your presentation has been too weak. I do really believe that adding a comparative and showing our strong points in the last slide would have worked better”.
Really few times negative criticisms are shared in a constructive way. We haven’t been tought that such kind of criticisms exist. Maybe that’s the reason why best leaders are those who use this kind of criticisms with ease. And best workers are those who accept this kind of criticisms without feeling personally attacked.
obviously you’re not satisfied with John’s work, but explaining him where the failures are will help him to understand your strategy. If you let him to share his counter-opinion, and you end with a smile and a “Next time we will nail it!”, next time John will be hyper-motivated.
Also KPIs are a kind of Negative constructive criticism. A KPI showing a sinking trend can be understood as a negative criticism of your strategy, but it keeps being a constructive one since it points you where your strategy is failing.
Negative destructive criticism.
“John, your presentation has been too weak. I didn’t like it at all. Sorry, but not.”
This is the Queen of criticism. You can find 15 of these one per one of the others. I bet you’ve been criticized at least once in this way or that you’ve already used it.
Back to the example: Why didn’t you like it? What is wrong with his presentation? My 3 years old neighbor can explain himself better than that. As a result John will return back home just thinking about the time wasted, and cursing in loud voice. That’s why it is destructive. It doesn’t help at all but, even worse, our message will strike us back.
Positive destructive criticism.
“John, I loved your presentation. You are my hero. The best worker/boss around.”
Can a positive criticism be destructive at the same time? You’ve a great example above. It’s the typical flattery. If someone tells you are an “ace” without any more reasoning. Do you really believe it blindly? or could he not be sharing his real opinion?
Beware with potential “false friend” criticisms. On the other hand, if we’re really pleased with John’s work, we’re losing a great opportunity to share with him which key points in his presentation have really amazed us.
The importance of criticism.
A well-argued criticism leads to continuous improvement. Criticisms come from everywhere, but the most important bit is filtering all of them to keep just the constructive (being positive or negative) ones. The destructive ones, even when positive, shouldn’t bias you when analyzing your strategy. Even more, these latter ones, can really confuse you. Haven’t you ever heard a “Your product is amazing. We’ll call you soon” but such call never taking place?
Probably the hardest task is to accept and to learn how-to formulate negative constructive criticisms.
Learning to accept negative constructive criticisms will help us to improve our work and strategy, and knowing how to formulate them will help us to add extra value to other’s work. Keep in mind that the best leader and the best worker are the ones mastering this kind of criticisms.
Probably one of the funniest moments while developing is when you realize that something that “looks easy” is not as straight forward as it seemed at first sight.
The task was “really easy”: Just creating a console app which (1)loops infinitely, (2)doing some tasks and (3) which breaks when the user decides to stop it (4)printing some valuable info before exiting.
“Naaah, this is easy. I just need a while/for/do-while/whatever infinite loop, a printf message asking the user to press a specific key to stop it, then a getch() to capture the key in order to break/stop the loop, and finally another printf to print the valuable info: PROFIT!”…2 minutes, or not?
The skeleton of your first mental approach could be something similar as the following one (you can find all the code in the CtrlHandler folder of my GitHub).
Maybe you’ve already noticed it (or if not, you will, as soon as you try to run it) but this app won’t work. Or better said, it won’t work as we expect.
Keep 2 or 3 minutes the app running, then press “5” (ASCII code 53). You could be expecting dCount to be about 120-180 (since the loop takes about 1 second because the Sleep). However the result is zero.
Try running it again, this time press 2, then 4, then 6, and finally our magic number “5”. The result is: 3
Basically what is happening is that our loop is not looping at all. When the getchar() call happens, the app will sit there staring you with its lovely catty eyes waiting a key to be pressed and, the best of all, blocking the loop execution until, of course, you press a key. Then and just then the while body is executed if the key pressed is not 5.
In other words: We will need to press a key once per loop. Not even close about what we want to do.
Then the getchar() dance starts: the call is moved to the top of the loop, then to the bottom, then to the conditional part of the loop, then above the loop(in a desperate move), then again to the body of the loop(because obviously outside of it hasn’t help at all). Nothing works.
“Oh,ok,lets change the getchar() logic to stop the loop by pressing ANY key”.
Cool. Now the app just loops once, it requests a key press to continue and of course…it stops there because you will press ANY key.
“This should be easy”. We breath now for the first time since the endless dance of CTL+X-CTRL+V-F7-ALT+TAB-UP-ENTER started.
“The problem is getchar() itself. It blocks. I want the same but non-blocking, accepting my key press input at any time during the loop, going on execution if I didnt press any”.
We scratch our head trying to find the name of such function call. And we dont find it.
“This should be easier than that..or, wait…(now the developer rage appears)… I can create an app with two threads, one for capturing user input, other for looping. It won’t be easy anymore but it will work for sure.”
Not a bad solution. But if we are over-engineering it, let me use this problem to show you a nice trick.
As you may know, if you press CTRL+C in the console while you are executing a program, this combination will kill inmediatly its execution.
The good news: To begin with you don’t need to add any getchar() or special code to handle the CTRL+C key press so we can let the app to loop wildly doing some tasks and tell the user to press CTRL+C when he wants to stop it. So requirements (1), (2) and (3) are covered without writing a single line of code.
The bad news: CTRL+C kills immediately the program. That means requirement (4) is not met. We wouldn’t be able to print, ie, the number of loops done. Also this kill is so rude, that we could end with files corrupted(if the loop was working with them) or we may have left some temporary files around that should have been deleted at the end of the program.
From Dr Jekyll to Mr Hide
So what if we could handle this CTRL+C to NOT kill inmediatly the program but to do that in a controlled way?
For such we will be using the SetConsoleCtrlHandler API. This API receives two params, the first one is the name of a function that will define the new behavior of CTRL+C (I’ve named it SignalHandler in my code) and a second one, which acts as a switch.
Let’s look first this second param: If the value is TRUE, the behavior of CTRL+C will follow the one defined in the function SignalHandler. If it is FALSE, SignalHandler is “deactivated”, and the CTRL+C will act again as a rude killer. This switch could be useful, then, to turn on/off the CTRL+C behavior dynamically from Dr Jekyll to Mr Hide as our wish.
Check the following code. Explanation follows:
Regarding the SignalHandler there are just two must haves: The function has to return a BOOL and to accept one param. The SetConsoleCtrlHandler API basically will send to it the CTRL_C_EVENT when the user presses CTRL+C. Of course it is not the only message that this API will/can send to our function, so the easiest way is to check which one we’re receiving by using a switch-case inside our SignalHandler implementation . More about other messages later. Our switch-case is pretty tiny, it just modifies a global variable called exitFlag, which controls the infinite loop in our main body. But of course you could be calling other functions or performing other steps. To sum up you can redefine the Ctrl+C behavior as you wish. We should return TRUE to let it know we’re modifying the signal behavior
As said, the SetConsoleCtrlHandlerAPI doesn’t just send the CTRL_C_EVENT but will redirect to our SignalHandler some others. In the previous example we’ve just ignored all the others so the console will keep their default behaviors and just override the Ctrl+C one. If the user would have pressed CTRL+BREAK which is, as you may know, another way to kill rudely a console app, our app would have been rudely killed.
Of course we can control and redefine the CTRL+BREAK behavior too as you can see in the image above, for such we have just to manage the CTRL_BREAK_EVENT in our function. Other messages we can handle are CTRL_CLOSE_EVENT, CTRL_LOGOFF_EVENT and CTRL_SHUTDOWN_EVENT. The first one is sent (“happens”) when the user closes the console window (a neat way to kill the app running). In this case we can’t abort the closing action but handling the message will let us to perform any tasks before being closed. In other words, we won’t let the closing happens until the app ends its work. The CTRL_LOGOFF_EVENT message will happen when the user logs off, so handling the message will give you a last chance before logging off happens (this signal is useful just for services). In the following example I’m controlling some of these signals.
Being immune to Mr Hyde
As always some APIs have some nice features hidden. This is the case of SetConsoleCtrlHandler. As explained this API expects as first param the name of a function, however, we can feed it with “NULL” (why not?).
In such case, CTRL+C signal WILL NEVER be sent to our app!. So our app will be immune to be killed via CTRL+C (however it can still be killed by CTRL+Break). A nice sup3rpow3r.
In the case we want be inmune to CTRL+C but still handle the rest of the signals we have just to call SetConsoleCtrlHandler twice: one with SignalHandler as param and one with the NULL one.
One detail: As you can see I’ve placed the SetConsoleCtrlHandler() with SignalHandler param above the SetConsoleCtrlHandler() with NULL param call. As you can see SignalHandler function tries to catch the CTRL+C signal, but it never prints the “CTRL+C can’t be never received” message. So basically at that time the CTRL+C signal is already deactivated, even if it is the first call, because the existence of a SetConsoleCtrlHandler() with NULL param.
You can find a binary ready to be tested in the bin folder of the Github repo. The Source folder contains the source code of this latest version, and the Replace&Try folder has the previous versions of the app so you can just replace the file and compile. Feel free to play with it and send new versions of the file.
Just using the excuse of breaking an infinite loop in a console app when an user desires we’ve ended studying SetConsoleCtrlHandler. This API opens doors to a lot of interesting features as controlling signals like CTRL+C or CTRL+BREAK as user input, calling cleanup routines just before exiting to avoid left overs, or even making our console app immune to the CTRL+C signal.
If you want to exit the loop in the original problem when an user presses any key without controlling CTRL+C as we did, you may want to give a look to the _kbhit() function. If you want to break the loop with a specific key, you could combine_kbhit and getchar calls.. Just an advise: Good luck managing the Enter key.
I need to know if he is a good or bad investor...
We’re trying to find an investor, the project is about to hit the market and we need a final push ^^.
It’s our first project, and we’re afraid of the “investor weirdos” out there. Knowing you’ve direct contact with “real” investors, may you share any tips to help us detect fake investors?
Thanks a lot! RosaEmprendedora
This is, no doubts, one of the most frequent asked questions, and probably it’d need several blog posts. However, there’re several signs that should alert you when talking with an investor. Hope this helps you to distinguish “himbestors” from real investors.
1 – The investor approached you in an entrepreneur event.
There are real investors who joins entrepreneur evenst but, with few exceptions, most of them are usually “himbestors”. Main reasons: An investor doesn’t have time to join this kind of events (or he doesn’t want to be part of such pain in the neck), he has zillions of projects knocking his door directly (why joining an event to find them?) and last, but not least, waiting your approach puts him at a better position in a potential deal.
2 – The investors seems interested in your project but he doesn’t ask you about how much (or what) you need.
Usually an investor will ask you details about your project. It would be pretty odd otherwise. However dull “himbestors” will try to avoid asking you 3 key questions: How much do you need?, Which is the return of my investment?, When will your bussiness break-even?
Add +1 in the “himbestor” balance for each of the previous questions not asked. There are really dull “himbestors”.
3 – The “himbestor” seeks his own benefit. The investor seeks the benefit through your company.
Maybe you’ve always heard investors seek their own benefit. That’s true (obviously), but not totally right. An investor seeks such benefit but thanks to your (and now his) company. Basically when he invests he is becoming a co-owner of your startup, so if the company moves forward, he wins, but if your startup shinks, he loses. Investors don’t expect your startup to be profitable in the short term (its first year) but in the medium and long term.
An “himbestor”, however, seeks his own direct, instant, benefit. If you feel an investor is puzzled about your company not being profitable the first year, and he presses with questions about it …run away! He is preparing the game field to show himself and, probably, to sell his services.
4 – Which is your 5-year Business Plan?
There are tons of investors reading this blog, and they can assure you that 90% of the 5-years bussiness plans predictions of the startups they’ve already invested have never been met.
An investors is going to ask you to tell, and explain, him your 5-years plan. But his main objective is to know your team better and to understand your strategic vision. He is not really interested in your crafted numbers.
An “hinvestor”, however, will keep asking about your 3-years and 5-years numbers, he will even tell you in loud voice he doesn’t trust such numbers. There are better ways to understand the viability of your startup and he is missing them.
So, if 50% of the talk is spinning around the credibility of the numbers of your business plan, slam the door in his face. Breath. You’ve just discover an “himbestor”.
5 – Talk evolves in the wrong direction.
Don’t let him to unfocus you from your main objective. If you feel the conversation has slowly evolved from a “I have the money you need” to “I can try to find the money you need”, you’re in front of an “himbestor”.
His next sentence will be asking you a % of your startup in order to find for “sure” the investment you need due his “abroad expertise, blabla, chit-chat here, blublu”. Or maybe asking you a % of your company to pay his finantial/marketing/legal services (“I will make an unbeatable business plan for you”). If you’re trying to find money, then…he is not the guy.
Beware! I’m not against quality broker/agents nor entrepreneurs who can add a plus to your project. But if he approached showing himself as an investor to catch your eye…then…You-Know. Runaway! 🙂
6 – He asks you for your secret recipe.
Investors are not copying entrepreneurs’ ideas. They don’t have time, nor willing, nor…for such. That’s why they won’t never ask you for your “secret recipe”. If your startup in an online store to sell cakes, the investor will be mainly interested about knowing where, how and for how much you’re going to sell them. He is not going to request the source code of your online platform, nor your secret cake recipes. Probably (not initially but during the negotiation process) he will request a 3rd party technical report, or a piece of cake to test/taste it, or some pictures of them.
However, there are shameless-mugs hidden behind the “himbestor” mask (usually failed entrepreneurs and really short-minded ones) trying to “find” ideas. If you find an “himbestor” asking YOUR Coca-Cola recipe…move on. And move on not because the fear to be copied (if he failed is probably because his attitude and he will fail again) but because your time is money and you are losing it with an “himbestor”.
Hope you’re really succesful with your startup! Btw, if you give me an interesting % of your startup I could…(naah…just kidding).
I don’t believe you have to be better than everybody else. I believe you have to be better than you ever thought you could be.— Ken Venturi
Nullam in tristique sapien. Aenean in eros felis. Ut ligula felis, eleifend at quam sit amet, tempor efficitur erat. Integer hendrerit vitae arcu nec convallis. Sed ullamcorper enim eget sagittis auctor. Quisque pellentesque mollis metus ac pharetra. Fusce dictum tincidunt sagittis. Sed mattis nunc ex, sed vulputate neque volutpat eget. Class aptent taciti sociosqu ad litora torquent per conubia nostra, per inceptos himenaeos.
In ut erat massa. Quisque vitae luctus purus, at pulvinar purus. Donec eu cursus orci, in tincidunt erat. Etiam non blandit neque, eget scelerisque erat. Nullam hendrerit egestas rutrum. In ornare est sed velit vestibulum, ac porttitor erat ultricies. In et congue sapien, eget accumsan erat. Ut malesuada felis sit amet elit pulvinar cursus. Morbi dictum interdum nulla a scelerisque. Integer venenatis consectetur magna ut laoreet. Donec ut finibus sem, efficitur semper nibh. Cras erat mi, lacinia et purus et, mollis feugiat dui. Interdum et malesuada fames ac ante ipsum primis in faucibus. Nunc porttitor porta nisl, id tempus diam pharetra a. Quisque iaculis placerat est quis feugiat. Mauris at quam id massa porta ultrices at sed lacus.
Join us for the very first ReactOS Hackfest from Friday, 7th August to Wednesday, 12th August 2015, in the German city of Aachen.
Discover Germany’s most-Western city in the direct neighborhood of Belgium and the Netherlands. Within the historical city center, Aachen offers a scientific environment and a high density of pubs.
Let’s catch this atmosphere to code the week away and achieve great results as a team!
It is now time to plan your trip!
Flights and Accommodation won’t get cheaper.
Find all details on this Wiki page:
Don’t forget to add your ideas and travelling details to this page:
If you have any further questions, just drop Colin a line by E-Mail !
Looking forward to meet you!
So in the previous Blogpost we were able to replicate the issue with a local testcase. Amazing! Now it’s time to discover what’s really going on, and hence create a fix! Let’s fix once and for all this registry nightmare corruption!
Some background first…
First, in short words so you can follow me, the registry memory structure is divided into “leaves”. When one “leaf” is full of data, another “leaf” is created.
So the memory structure when creating just a couple of registry keys would look like this:
—————– Leaf1 ———–…—–
Child1 Child2 Child3 Child4 Child5
And when we reach the limit of the Leaf1 and we add one more child, we would have something like:
—————– Leaf1 ———–…———-
Child1 Child2 Child3 Child4 Child5 … Child4999
—————– Leaf2 ———–…———-
What Happens In ReactOS?
As you can see a new leaf has been created since there is no more storage in Leaf1.
The problem arises when the next child is added:
—————– Leaf1 ———–…———-
Child1 Child2 Child3 Child4 Child5 … Child4999
—————– Leaf2 ———–…———-
And if we add one more:
—————– Leaf1 ———–…———-
Child1 Child2 Child3 Child4 Child5 … Child4999
—————– Leaf2 ———–…———-
Child5002 Child5001 Child5000
Do you see what’s going on? They’re not properly sorted! Leaf2 should look like, instead:
—————– Leaf2 ———–…———-
Child5000 Child5001 Child5002
ReactOS, when there is just one Leaf, uses the CmpFindSubKeyInLeaf api to find the Subkey. This API does not need the keys to be sorted at all in the Leaf1, since it compares one by one all the memory entries to retrieve the proper Subkey in the Leaf. Not too efficient, but well, it was working nicely.
The first test we created, the one which was adding and deleting just one key, obviously was not forcing the creation of a second Leaf, so the bug was not shown at all.
However, the second test was creating, first, 10.000 Childs (and hence forcing a new Leaf to be created) and afterwards deleting the entries. This wouldn’t be an issue if CmpFindSubKeyInLeaf was still used to find the Subkey, let’s say Child5002, since this API does not need keys to be sorted.
Then where is the bug?
The memory structure was looking like:
Child1 Child2 Child3 Child4 Child5 … Child4999—————– Leaf2 ———–…———-
Child5002 Child5001 Child5000
The issue with CmpFindSubKeyInLeaf is that it’s obviously non-efficient at all. It can work if you have just one leaf, however if you have 10 Leaves, you would be wasting too much cycles just to find a Key since it compares each key one by one. Imagine going through 9997 Childs to discover that the subkey needed is in Child9998.
That’s the reason ReactOS uses a different API when more than one leaf are present in memory: CmpCompareInIndex
The Awesome CmpCompareInIndex…
CmpCompareInIndex is used inside a binary-search algorithm. A binary-search algorithm needs by definition to have all the items in the leaves properly sorted.
This binary search algorithm begins using the last value of the Leafs to know in which Leaf it has to check for the value.
Imagine the case we are searching for “Child2000”, our binary search algorithm checks that the ending values in Leaf1 is Child4999, so it then checks inside that leaf by splitting the range in half. Since the values are properly sorted, then, the “Child2000” is, after some iterations, properly found.
Now, imagine the case we are searching for “Child5001”, well, it checks the Leaf1 ending value and discovers it is “Child4999”, so the algorithm discards Leaf1 because Child5001 is a bigger value. Then it checks Leaf2 ending value to discover it is “Child5000” (Remember: bugged sorting!), so it does not find a “proper” place where to add/delete the new value. Or worse, it does: Corrupting the registry! Voila!
The first fix created was to avoid using the CmpCompareInIndex, and using CmpFindSubKeyInLeaf instead, even if there was more than one leaf. This patch was created mainly as a workaround (it was not too efficient) until proper sorting were implemented, and also to find if our guess was correct or not.
Thankfully, the guess was correct and we were able to install JRE 7 without any issues!
Once we confirmed the bug, Zefklop committed a fix to sort the Childs correctly, since as you can see they were not so messed, and voila! he fixed the latest issue of the JRE 7 installer!
This one issue took too many hours, Devs and Testers to track it down.. but that has enhanced ReactOS stability as a whole.
Did I say this is the latest bug in JRE7 installer?
Nope. I lied.
There was one more annoying bug, but…it’ll have to wait until next post… 😉
Trying to fix Java 7RE support in ReactOS led us to find several bugs in a row.
First we found ourselves a “big” bug when installing Java 7 which was making ReactOS to show a nice-bluish window of death. We, then, decided to check if Java 6 was installing and running, and while it installs, well..it was suffering a big memory manager bug: The Pool bug.
Now, once the Pool bug is fixed, it’s time to “go back to the future” and check again the Java 7RE setup issue.
The Setup Issue
As you may know the installer of an app is absolutly independent of the app itself. So in order to make Java 7RE working, you have first to deal with the “Java RE 7 installer.exe” and then with “Java.exe” itself.
When we tried to install JRE 7, the setup seemed to work pretty well until it reached the final stage.
During this final stage, JRE 7 installer was trying to copy several data into the ReactOS registry, but instead it was pushing ReactOS to crash in a beautiful blue window.
The only way to retry the setup is to reboot ReactOS, but this bug was so cumbersome that was making ReactOS totally unbootable.
As a result, JRE installer revealed a bug which does not just let JRE to be properly installed, but also trashing the whole ReactOS.
You can find here one of the reports about this issue, full of debuglogs and potential guesses about what was going on.
A Registry bug
If an app installer crashes while writing registry entries, well, then It’s easy to suppose that the bug is hidden in one of our registry apis. If the bug also prevents ReactOS to be booted, then, we’re talking about Registry Corruption which is a way more important bug (as important as preventing ReactOS booting at all!).
The Registry is, simple speaking, a…mmm…”tree” of folders and values. Corrupting the registry is not just “not copying” a value, but also modifying this tree in a wrong way so it can lead to “whoknows” behavior, in this case ReactOS not booting.
The Test Case
Thanks to several debugging sessions,
V and Vicmarcal(well, yes, that’s me), found what was going on.
For such, we analyzed the JRE7 installer behavior in Windows 2003, focused in the “Copy values to Registry” stage.
There we detected that JRE installer was trying to remove a registry key under CLSID (one of the “branchs” of the Registry “tree”).
We created a first testcase which mainly was creating and then removing a subkey in CLSID, however the testcase wasn’t breaking nor corrupting ReactOS at all as we’d expect.
Our second try was more succesful, we created a testcase which was creating 10.000 subkeys and deleting all but the Child5000. This trashed ReactOS in the exactly same way JDK was doing!
The idea of creating 10000 subkeys was due CLSID is one of the most populated “branchs” of the tree, so instead creating just one subkey, we tried creating 10000 to replicate as much as possible our CLSID-fake.
You can see here the bugreport with the testcase. The patch there is not the patch of the bug, but a patch to add this testcase into our apitests system so we can track that this bug never “comes to live” again.
Ok. Ok. But…where is the bug??
Well…you’ll have to wait ’til the next time!
Be prepared to be introduced to “leaves” and “trees”!