+ int ret;
+ DECOMPRESSOR_HANDLE h;
+
+ ERROR("clen=%u, ulen=%u, window_size=%u", clen, ulen, window_size);
+
+ if (hCabinetDll == NULL) {
+ pthread_mutex_lock(&cabinetDllMutex);
+
+ if (hCabinetDll == NULL) {
+ hCabinetDll = LoadLibrary(L"Cabinet.dll");
+
+ if (hCabinetDll == NULL) {
+ ERROR("Can't load Cabinet.dll");
+ ret = -1;
+ goto unlock;
+ }
+
+ CreateDecompressor = (void*)GetProcAddress(hCabinetDll, "CreateDecompressor");
+ Decompress = (void*)GetProcAddress(hCabinetDll, "Decompress");
+ CloseDecompressor = (void*)GetProcAddress(hCabinetDll, "CloseDecompressor");
+
+ if (CreateDecompressor == NULL ||
+ Decompress == NULL ||
+ CloseDecompressor == NULL)
+ {
+ ERROR("Can't find LZMS compression routines in Cabinet.dll");
+ ret = -1;
+ goto unlock;
+ }
+ }
+ ret = 0;
+ unlock:
+ pthread_mutex_unlock(&cabinetDllMutex);
+ if (ret)
+ goto out;
+ }
+
+
+ if (!CreateDecompressor(COMPRESS_ALGORITHM_LZMS | COMPRESS_RAW, NULL, &h)) {
+ ERROR("Failed to create LZMS decompressor (err %d)!", GetLastError());
+ ret = -1;
+ goto out;
+ }
+
+
+ /* TODO: Some sort of chunk header? */
+ unsigned offset;
+ if (clen <= window_size) {
+ offset = 0;
+ } else {
+ const unsigned *p = cbuf;
+ ERROR("%08x(%u) %08x %08x %08x %08x(%u)",
+ p[0], p[0], p[1], p[2], p[3], p[4], p[4]);
+ offset = 20;
+ }
+ SIZE_T actual_ulen = -1;
+ if (!Decompress(h, (void*)cbuf + offset, clen - offset, ubuf, ulen, &actual_ulen)) {
+ ERROR("Failed to decompress LZMS-compressed data (err %d)!", GetLastError());
+ ret = -1;
+ goto out_close_decompressor;
+ }
+
+ if (actual_ulen != ulen) {
+ ERROR("Unexpected actual uncompressed length (got %u, expected %u)",
+ actual_ulen, ulen);
+ ret = -1;
+ goto out_close_decompressor;
+ }
+
+ ERROR("Successfully decompressed data.");
+ ret = 0;
+out_close_decompressor:
+ CloseDecompressor(h);
+out:
+ return ret;