by hbelusca | November 20, 2016

In this second report I continue my investigations on the Word 2010 installation. Last time we saw that our services (and in particular the "Office Software Protection Platform" OSPPSVC service) were started without a complete environment block, and as a result some needed environment variables were missing, causing e.g. OSPPSVC to fail opening some of its files. We now analyse what happens after my local fix (NOTE: I have not committed the fix yet, as I validate it in my local installation first).

Retesting the installation (hacked way)

After having fixed the environment variables problem, I decided to retry the Word 2010 installation. Sadly it again failed at the same place (MSI action "CAInitSPPTokenStore.x86" failure with error 1603), so I decided to attempt to see what happened if I worked around the failure. I placed breakpoints in our MSI code where the installation error is caught, in order to overwrite the failure error code with a success code ( 0: ERROR_SUCCESS ) to make the installation continue, and thanks to that I was able to finish the installation. This allowed me to confirm that only the MSI action "CAInitSPPTokenStore.x86" actually failed.

Breakpoint in MSI code

Running the installation and stepping in the code

Hitting the error

Forcing the error to be 0 and continuing execution

Installation finished after working around the errors

Here are some additional pictures of Word 2010 installed in ReactOS:

Word 2010 files

Word 2010 shortcuts

However, trying to run Word in ReactOS triggers again the installer, which attempts to perform extra configuration steps. This does not happen on a successful installation in Win2k3. This is certainly due to the fact that the OSPPSVC was not able to initialize correctly itself and I was forced to manually skip its configuration step at installation time.

Configuration while starting Word 2010

Word installation asks for a restart

Word cannot verify its own license

Translation: "Microsoft Office cannot verify the license for this product. You should repair the Office installation from within the Configuration Panel"

So far, the installation succeeded just because I overwrote the error codes due to the MSI action "CAInitSPPTokenStore.x86" that was failing, with a success error code. While this procedure allows me to confirm that only this step in the installation process fails and everything else seems to work so far, the procedure does not shed light on why the MSI action fails in the first place.

OSPPSVC service investigation 2/2, and MSI installation (cont.)

With advice from Sylvain Petreolle, I searched through the temporary generated MSI files which one(s) referred to the "CAInitSPPTokenStore" action. (Note: during installation the MSI framework creates temporary PE files corresponding to the different MSI actions performed during the installation, that can be rolled back in case the user cancelled the installation, or an error occurred during the process. The MSI action itself shows as an exported function, that is subsequently called by the MSI framework.) I then analysed what was done inside this action, and noticed that it first just stopped the OSPPSVC service, with some code following a pattern similar to that described in the JIRA report CORE-12413, and then performed an external DLL API call, then restarts OSPPSVC. I therefore made a first hypothesis that something should went wrong when we try stopping / querying a service status. While this problem actually really happens when the service is started, then stopped manually, this generally does not appear to be the case during a clean Office installation because the service is initially stopped. So the problem should arise after. The observed problem looks similar as (but the causes certainly are different than) what is described at this link (MS Office forum).

Performing a step-by-step debugging inside this MSI action let me allowed to find the second and crucial problem. After the OSPPSVC service is stopped the MSI action calls the SLInitialize function that is exported by a DLL named OSPPCEXT.DLL (a helper for the Office Software Protection service). This function, which sadly is partially crypted (and is decrypted at run-time: this is recognizable by the fact that its first bytes are constituted of valid code that ends with a call to a subfunction, and the following bytes are seemingless data; the subfunction performs some operations using the CPU instruction pointer, and returns as a regular function, to its caller). The SLInitialize function returns with an error code that makes the MSI action fail.