summaryrefslogtreecommitdiff
path: root/src/ToolBox/superpmi/mcs/verbconcat.cpp
blob: 36620f11b2c241309e13f653ae5f5b935d828645 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
//
// Copyright (c) Microsoft. All rights reserved.
// Licensed under the MIT license. See LICENSE file in the project root for full license information.
//

#include "standardpch.h"
#include "verbconcat.h"
#include "simpletimer.h"
#include "logging.h"

#define BUFFER_SIZE 0xFFFFFF

int verbConcat::DoWork(const char *nameOfFile1, const char *nameOfFile2)
{
    SimpleTimer st1;

    LogVerbose("Concatenating '%s'+'%s' into %s", nameOfFile1, nameOfFile2, nameOfFile1);

    LARGE_INTEGER DataTemp1;
    LARGE_INTEGER DataTemp2;

    HANDLE hFileIn1 = CreateFileA(nameOfFile1, GENERIC_READ|GENERIC_WRITE, 0, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if(hFileIn1 == INVALID_HANDLE_VALUE)
    {
        LogError("Failed to open input 1 '%s'. GetLastError()=%u", nameOfFile1, GetLastError());
        return -1;
    }
    if(GetFileSizeEx(hFileIn1, &DataTemp1)==0)
    {
        LogError("GetFileSizeEx failed. GetLastError()=%u", GetLastError());
        return -1;
    }

    LONG highDWORD = 0;
    DWORD dwPtr = SetFilePointer(hFileIn1, 0, &highDWORD, FILE_END);
    if (dwPtr == INVALID_SET_FILE_POINTER)
    {
        LogError("Failed to SetFilePointer on input 1 '%s'. GetLastError()=%u", nameOfFile1, GetLastError());
        return -1;
    }

    HANDLE hFileIn2 = CreateFileA(nameOfFile2, GENERIC_READ, FILE_SHARE_READ, NULL, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL|FILE_FLAG_SEQUENTIAL_SCAN, NULL);
    if(hFileIn2 == INVALID_HANDLE_VALUE)
    {
        LogError("Failed to open input 2 '%s'. GetLastError()=%u", nameOfFile2, GetLastError());
        return -1;
    }
    if(GetFileSizeEx(hFileIn2, &DataTemp2)==0)
    {
        LogError("2nd GetFileSizeEx failed. GetLastError()=%u", GetLastError());
        return -1;
    }

    unsigned char* buffer = new unsigned char[BUFFER_SIZE];

    st1.Start();
    for(LONGLONG offset = 0; offset < DataTemp2.QuadPart; offset += BUFFER_SIZE)
    {
        DWORD bytesRead = -1;
        BOOL res = ReadFile(hFileIn2, buffer, BUFFER_SIZE, &bytesRead, nullptr);
        if(res == 0)
        {
            LogError("Failed to read '%s' from offset %lld. GetLastError()=%u", nameOfFile2, offset, GetLastError());
            return -1;
        }
        DWORD bytesWritten = -1;
        BOOL res2 = WriteFile(hFileIn1, buffer, bytesRead, &bytesWritten, nullptr);
        if(res2 == 0)
        {
            LogError("Failed to write '%s' at offset %lld. GetLastError()=%u", nameOfFile1, offset, GetLastError());
            return -1;
        }
        if(bytesRead!=bytesWritten)
        {
            LogError("Failed to read/write matching bytes %u!=%u", bytesRead, bytesWritten);
            return -1;
        }
    }
    st1.Stop();

    delete[] buffer;

    if(CloseHandle(hFileIn1)==0)
    {
        LogError("CloseHandle failed. GetLastError()=%u", GetLastError());
        return -1;
    }
    if(CloseHandle(hFileIn2)==0)
    {
        LogError("2nd CloseHandle failed. GetLastError()=%u", GetLastError());
        return -1;
    }

    LogInfo("Read/Wrote %lld MB @ %4.2f MB/s.\n",
            DataTemp2.QuadPart/(1000*1000),
            (((double)DataTemp2.QuadPart)/(1000*1000))/st1.GetSeconds()); //yes yes.. http://en.wikipedia.org/wiki/Megabyte_per_second#Megabyte_per_second

    return 0;
}