StdStrBuf StdCompilerConfigRead::ReadString()
{
	// Virtual key?
	if (pKey->Virtual)
		{ excNotFound("Could not read value %s! Parent key doesn't exist!", pKey->Name.getData()); return StdStrBuf(); }
	// Wrong type?
	if (pKey->Type != REG_SZ)
		{ excNotFound("Wrong value type!"); return StdStrBuf(); }
	// Get size of string
	DWORD iSize;
	if (RegQueryValueExW(pKey->Parent->Handle, pKey->Name.GetWideChar(),
	                    0, NULL,
	                    NULL,
	                    &iSize) != ERROR_SUCCESS)
		{ excNotFound("Could not read value %s!", pKey->Name.getData()); return StdStrBuf(); }
	// Allocate string
	StdBuf Result; Result.SetSize(iSize);
	// Read
	if (RegQueryValueExW(pKey->Parent->Handle, pKey->Name.GetWideChar(),
	                    0, NULL,
	                    reinterpret_cast<BYTE *>(Result.getMData()),
	                    &iSize) != ERROR_SUCCESS)
		{ excNotFound("Could not read value %s!", pKey->Name.getData()); return StdStrBuf(); }
	// Check size
	if (wcslen(getBufPtr<wchar_t>(Result)) + 1 != iSize / sizeof(wchar_t))
		{ excCorrupt("Wrong size of a string!"); return StdStrBuf(); }
	return StdStrBuf(getBufPtr<wchar_t>(Result));
}
Exemple #2
0
StdBuf C4Playback::ReWriteBinary() {
  const int OUTPUT_GROW = 16 * 1024;
  StdBuf Output;
  int iPos = 0;
  bool fFinished = false;
  uint32_t iFrame = 0;
  for (chunks_t::const_iterator i = chunks.begin();
       !fFinished && i != chunks.end(); i++) {
    // Check frame difference
    if (i->Frame - iFrame < 0 || i->Frame - iFrame > 0xff)
      LogF(
          "ERROR: Invalid frame difference between chunks (0-255 allowed)! "
          "Data will be invalid!");
    // Pack data
    StdBuf Chunk;
    try {
      switch (i->Type) {
        case RCT_Ctrl:
          Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pCtrl);
          break;
        case RCT_CtrlPkt:
          Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pPkt);
          break;
        case RCT_End:
          fFinished = true;
          break;
        default:  // debugrec
          if (i->pDbg) Chunk = DecompileToBuf<StdCompilerBinWrite>(*i->pDbg);
          break;
      }
    } catch (StdCompiler::Exception *pEx) {
      LogF("Record: Binary unpack error: %s", pEx->Msg.getData());
      delete pEx;
      return StdBuf();
    }
    // Grow output
    while (Output.getSize() - iPos <
           sizeof(C4RecordChunkHead) + Chunk.getSize())
      Output.Grow(OUTPUT_GROW);
    // Write header
    C4RecordChunkHead *pHead = getMBufPtr<C4RecordChunkHead>(Output, iPos);
    pHead->Type = i->Type;
    pHead->iFrm = i->Frame - iFrame;
    iPos += sizeof(C4RecordChunkHead);
    iFrame = i->Frame;
    // Write chunk
    Output.Write(Chunk, iPos);
    iPos += Chunk.getSize();
  }
  Output.SetSize(iPos);
  return Output;
}
Exemple #3
0
bool C4Playback::NextSequentialChunk() {
  StdBuf BinaryBuf;
  size_t iRealSize;
  BinaryBuf.New(4096);
  // load data until a chunk could be filled
  for (;;) {
    iRealSize = 0;
    playbackFile.Read(BinaryBuf.getMData(), 4096, &iRealSize);
    if (!iRealSize) return false;
    BinaryBuf.SetSize(iRealSize);
    if (!ReadBinary(BinaryBuf)) return false;
    // okay, at least one chunk has been read!
    if (chunks.size()) {
      currChunk = chunks.begin();
      return true;
    }
  }
  // playback file reading failed - looks like we're done
  return false;
}
Exemple #4
0
void C4Playback::Check(C4RecordChunkType eType, const uint8_t *pData,
                       int iSize) {
  // only if enabled
  if (DoNoDebugRec > 0) return;
  if (Game.FrameCounter < DEBUGREC_START_FRAME) return;

  C4PktDebugRec PktInReplay;
  bool fHasPacketFromHead = false;
#ifdef DEBUGREC_EXTFILE
#ifdef DEBUGREC_EXTFILE_WRITE
  // writing of external debugrec file
  DbgRecFile.Write(&eType, sizeof eType);
  int32_t iSize32 = iSize;
  DbgRecFile.Write(&iSize32, sizeof iSize32);
  DbgRecFile.Write(pData, iSize);
  return;
#else
  int32_t iSize32 = 0;
  C4RecordChunkType eTypeRec = RCT_Undefined;
  DbgRecFile.Read(&eTypeRec, sizeof eTypeRec);
  DbgRecFile.Read(&iSize32, sizeof iSize32);
  if (iSize32) {
    StdBuf buf;
    buf.SetSize(iSize32);
    DbgRecFile.Read(buf.getMData(), iSize32);
    PktInReplay = C4PktDebugRec(eTypeRec, buf);
  }
#endif
#else
  // check debug rec in list
  C4IDPacket *pkt;
  if (pkt = DebugRec.firstPkt()) {
    // copy from list
    PktInReplay = *static_cast<C4PktDebugRec *>(pkt->getPkt());
    DebugRec.Delete(pkt);
  } else {
    // special sync check skip...
    while (currChunk != chunks.end() && currChunk->Type == RCT_CtrlPkt) {
      C4IDPacket Packet(*currChunk->pPkt);
      C4ControlPacket *pCtrlPck =
          static_cast<C4ControlPacket *>(Packet.getPkt());
      assert(!pCtrlPck->Sync());
      Game.Control.ExecControlPacket(Packet.getPktType(), pCtrlPck);
      NextChunk();
    }
    // record end?
    if (currChunk == chunks.end() || currChunk->Type == RCT_End || Finished) {
      Log("DebugRec end: All in sync!");
      ++DoNoDebugRec;
      return;
    }
    // unpack directly from head
    if (currChunk->Type != eType) {
      DebugRecError(FormatString("Playback type %x, this type %x",
                                 currChunk->Type, eType).getData());
      return;
    }
    PktInReplay = *currChunk->pDbg;
    fHasPacketFromHead = true;
  }
#endif  // DEBUGREC_EXTFILE
  // record end?
  if (PktInReplay.getType() == RCT_End) {
    Log("DebugRec end: All in sync (2)!");
    ++DoNoDebugRec;
    return;
  }
  // replay packet is unpacked to PktInReplay now; check it
  if (PktInReplay.getType() != eType) {
    DebugRecError(FormatString("Type %s != %s",
                               GetRecordChunkTypeName(PktInReplay.getType()),
                               GetRecordChunkTypeName(eType)).getData());
    return;
  }
  if (PktInReplay.getSize() != iSize) {
    DebugRecError(FormatString("Size %d != %d", (int)PktInReplay.getSize(),
                               (int)iSize).getData());
  }
  // check packet data
  if (memcmp(PktInReplay.getData(), pData, iSize)) {
    StdStrBuf sErr;
    sErr.Format("DbgRecPkt Type %s, size %d", GetRecordChunkTypeName(eType),
                iSize);
    sErr.Append(" Replay: ");
    StdBuf replay(PktInReplay.getData(), PktInReplay.getSize());
    sErr.Append(GetDbgRecPktData(eType, replay));
    sErr.Append(" Here: ");
    StdBuf here(pData, iSize);
    sErr.Append(GetDbgRecPktData(eType, here));
    DebugRecError(sErr.getData());
  }
  // packet is fine, jump over it
  if (fHasPacketFromHead) NextChunk();
}
Exemple #5
0
bool C4Playback::StreamToRecord(const char *szStream, StdStrBuf *pRecordFile) {
  // Load data
  StdBuf CompressedData;
  Log("Reading stream...");
  if (!CompressedData.LoadFromFile(szStream)) return false;

  // Decompress
  unsigned long iStreamSize = CompressedData.getSize() * 5;
  StdBuf StreamData;
  StreamData.New(iStreamSize);
  while (true) {
    // Initialize stream
    z_stream strm;
    ZeroMem(&strm, sizeof strm);
    strm.next_in = getMBufPtr<BYTE>(CompressedData);
    strm.avail_in = CompressedData.getSize();
    strm.next_out = getMBufPtr<BYTE>(StreamData);
    strm.avail_out = StreamData.getSize();

    // Decompress
    if (inflateInit(&strm) != Z_OK) return false;
    int ret = inflate(&strm, Z_FINISH);
    if (ret == Z_STREAM_END) {
      inflateEnd(&strm);
      break;
    }
    if (ret != Z_BUF_ERROR) return false;

    // All input consumed?
    iStreamSize = strm.total_out;
    if (strm.avail_in == 0) {
      Log("Stream data incomplete, using as much data as possible");
      break;
    }

    // Larger buffer needed
    StreamData.Grow(CompressedData.getSize());
    iStreamSize = StreamData.getSize();
  }
  StreamData.SetSize(iStreamSize);

  // Parse
  C4Playback Playback;
  Playback.ReadBinary(StreamData);
  LogF("Got %d chunks from stream", Playback.chunks.size());

  // Get first chunk, which must contain the initial
  chunks_t::iterator chunkIter = Playback.chunks.begin();
  if (chunkIter == Playback.chunks.end() || chunkIter->Type != RCT_File)
    return false;

  // Get initial chunk, go over file name
  StdBuf InitialData = *chunkIter->pFileData;
  const char *szInitialFilename = chunkIter->Filename.getData();

  // Put to temporary file and unpack
  char szInitial[_MAX_PATH + 1] = "~initial.tmp";
  MakeTempFilename(szInitial);
  if (!InitialData.SaveToFile(szInitial) || !C4Group_UnpackDirectory(szInitial))
    return false;

  // Load Scenario.txt from Initial
  C4Group Grp;
  C4Scenario Initial;
  if (!Grp.Open(szInitial) || !Initial.Load(Grp) || !Grp.Close()) return false;

  // Copy original scenario
  const char *szOrigin = Initial.Head.Origin.getData();
  char szRecord[_MAX_PATH + 1];
  SCopy(szStream, szRecord, _MAX_PATH);
  if (GetExtension(szRecord)) *(GetExtension(szRecord) - 1) = 0;
  SAppend(".c4s", szRecord, _MAX_PATH);
  LogF("Original scenario is %s, creating %s.", szOrigin, szRecord);
  if (!C4Group_CopyItem(szOrigin, szRecord, false, false)) return false;

  // Merge initial
  if (!Grp.Open(szRecord) || !Grp.Merge(szInitial)) return false;

  // Process other files in stream
  chunkIter->Delete();
  chunkIter = Playback.chunks.erase(chunkIter);
  while (chunkIter != Playback.chunks.end())
    if (chunkIter->Type == RCT_File) {
      LogF("Inserting %s...", chunkIter->Filename.getData());
      StdStrBuf Temp;
      Temp.Copy(chunkIter->Filename);
      MakeTempFilename(&Temp);
      if (!chunkIter->pFileData->SaveToFile(Temp.getData())) return false;
      if (!Grp.Move(Temp.getData(), chunkIter->Filename.getData()))
        return false;
      chunkIter = Playback.chunks.erase(chunkIter);
    } else
      chunkIter++;

  // Write record data
  StdBuf RecordData = Playback.ReWriteBinary();
  if (!Grp.Add(C4CFN_CtrlRec, RecordData, false, true)) return false;

  // Done
  Log("Writing record file...");
  Grp.Close();
  pRecordFile->Copy(szRecord);
  return true;
}