Few words about Microsoft interoperability initiative.
As you probably know, Microsoft released last month several thousands pages of documentation about office file format and Windows protocols.
It means numerous hundreds(thousands?) of functions/algorithms documentation and pseudo-code. But, are these pseudo-function right? It looks not.
While I was reading [MS-DRSR]: Directory Replication Service (DRS) Remote Protocol Specification, I was a bit curious to see the DecompressWin2k3() function (Thanks Aaron, Stefan , and Brendan).
This function is in fact the decompression algorithm called Xpress implemented for the first time in Windows XP and not Windows 2003 as say the name. Xpress algorithm works on 64kb chunks and is used in Windows hibernation file format, Windows Imaging Format (WIM) , Outlook, Exchange, and… LDAP replication service of Active Directory.
I’m quoting below, errors I found in the pseudo-code of DecompressWin2k3(). Here is the C implementation.
while (outputIndex < = outputSize)
should be:
while (outputIndex < outputSize)
if (indicatorBit = 0) then
indicatorBit := copy inputBuffer[inputIndex] as 32-bit integer in
little-endian format
should be:
indicator := copy inputBuffer[inputIndex] as 32-bit integer in
little-endian format
inputIndex := inputIndex + 4
indicatorBit := 32
endif
indicatorBit := indicatorBit - 1
//* check whether the bit specified by indicatorBit is set or not
//* set in indicator. For example, if indicatorBit has value 4
//* check whether the 4th bit of the value in indicator is set
if indicatorBit bit in indicator is not set then
inputBuffer[inputIndex] := outputBuffer[outputIndex]
should be:
outputBuffer[outputIndex] := inputBuffer[inputIndex]
inputIndex := inputIndex + 1
outputIndex := outputIndex + 1
else
length := copy inputBuffer[inputIndex] as 16-bit integer in
little-endian format
inputIndex := inputIndex + 2
offset := length /8
length := length mod 8
if (length = 7) then
if (nibbleIndex = 0) then
nibbleIndex := inputIndex
length := inputBuffer[inputIndex] mod 16
inputIndex := inputIndex + 1
else
length := inputBuffer[inputIndex] / 16
should be:
length := inputBuffer[nibbleIndex ] / 16
nibbleIndex := 0
endif
if (length = 15) then
length := inputBuffer[inputIndex]
inputIndex := inputIndex + 1
if (length = 255) then
length := copy inputBuffer[inputIndex] as 16-bit integer in little-endian format
inputIndex := inputIndex + 2
length := length - (15 + 7)
endif
length := length + 15
endif
length := length + 7
endif
length := length + 3
while (not length = 0)
should be:
while (length != 0)
outputBuffer[outputIndex] := outputBuffer[outputIndex - offset - 1]
outputIndex := outputIndex + 1
length := length - 1
endwhile
endif
endwhile
return