Skip to content

Commit

Permalink
refactor to implement arguments
Browse files Browse the repository at this point in the history
  • Loading branch information
cwansart committed Sep 25, 2023
1 parent 9b9b15f commit 4274ca9
Show file tree
Hide file tree
Showing 10 changed files with 380 additions and 178 deletions.
4 changes: 2 additions & 2 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -1,2 +1,2 @@
main.obj
sha256sum.exe
*.obj
*.exe
7 changes: 7 additions & 0 deletions .vscode/settings.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
{
"files.associations": {
"sha256.h": "c",
"wchar.h": "c",
"args.h": "c"
}
}
2 changes: 1 addition & 1 deletion Makefile
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@ CFLAGS = /W4 /MD /O2
OUTFILE = sha256sum.exe

# Source files
SOURCES = main.c
SOURCES = main.c args.c sha256.c

# Object files (one per source file)
OBJECTS = $(SOURCES:.c=.obj)
Expand Down
32 changes: 32 additions & 0 deletions Makefile.tests
Original file line number Diff line number Diff line change
@@ -0,0 +1,32 @@
# Compiler
CC = cl

# Flags for the compiler
CFLAGS = /W4 /MD /O2

# Name of the final executable
OUTFILE = tests.exe

# Source files
SOURCES = tests.c args.c

# Object files (one per source file)
OBJECTS = $(SOURCES:.c=.obj)

# Default target
all: $(OUTFILE)

# Linking rule
$(OUTFILE): $(OBJECTS)
$(CC) $(CFLAGS) /Fe$@ $(OBJECTS) /link

# Compilation rule
.c.obj:
$(CC) $(CFLAGS) /c $< /Fo$@

# Clean rule
clean:
del *.obj $(OUTFILE)

# Phony targets
.PHONY: all clean
40 changes: 40 additions & 0 deletions args.c
Original file line number Diff line number Diff line change
@@ -0,0 +1,40 @@
#include "args.h"

errno_t parse_args(int argc, wchar_t *argv[], wchar_t **out_shasums_file)
{
if (argc < 2)
{
usage(argv[0], L"missing parameter");
return ARGS_MISSING_PARAMETER;
}

for (int i = 0; i < argc; ++i)
{
if (wcscmp(argv[i], L"-c") == 0)
{
// check if there is another argument after -c
if (i + 1 < argc)
{
*out_shasums_file = argv[i + 1];
++i; // skip next argument since we used it here
}
else
{
usage(argv[0], L"");
return ARGS_MISSING_SHASUMS_FILE;
}
}
}

return OK;
}

void usage(wchar_t *prog, wchar_t *message)
{
if (NULL != message)
{
fwprintf(stderr, L"%ls\n", message);
}

wprintf(L"Usage: %ls [-c sha256sums_file] [file...]\n", prog);
}
9 changes: 9 additions & 0 deletions args.h
Original file line number Diff line number Diff line change
@@ -0,0 +1,9 @@
#pragma once
#include <wchar.h>

#define OK 0
#define ARGS_MISSING_PARAMETER 1
#define ARGS_MISSING_SHASUMS_FILE 2

errno_t parse_args(int argc, wchar_t *argv[], wchar_t **out_shasums_file);
void usage(wchar_t *prog, wchar_t *message);
189 changes: 14 additions & 175 deletions main.c
Original file line number Diff line number Diff line change
@@ -1,189 +1,28 @@
#include <windows.h>
#include <stdio.h>
#include <bcrypt.h>
#include "args.h"
#include "sha256.h"

#pragma comment(lib, "bcrypt.lib")

#define NT_SUCCESS(Status) (((NTSTATUS)(Status)) >= 0)
#define STATUS_UNSUCCESSFUL ((NTSTATUS)0xC0000001L)
#define SET_FAILURE_AND_CLEANUP do { \
failure = TRUE; \
goto Cleanup; \
} while(0)

int __cdecl wmain(int argc, wchar_t *argv[])
int wmain(int argc, wchar_t *argv[])
{
BOOL failure = FALSE;
HANDLE hFile;
DWORD dwBytesRead;
BYTE buffer[1024] = {0};
wchar_t *shasums_file = NULL;

BCRYPT_ALG_HANDLE hAlg = NULL;
BCRYPT_HASH_HANDLE hHash = NULL;
NTSTATUS status = STATUS_UNSUCCESSFUL;
DWORD cbData = 0,
cbHash = 0,
cbHashObject = 0;
PBYTE pbHashObject = NULL;
PBYTE pbHash = NULL;

// read args
if (argc < 2)
errno_t parse_result = parse_args(argc, argv, &shasums_file);
if (parse_result != OK)
{
wprintf(L"missing file parameter\n");
wprintf(L"usage: %ls <filename>\n", argv[0]);
return 1;
}

// open file
hFile = CreateFileW(argv[1], // File name
GENERIC_READ, // Open for reading
0, // No sharing
NULL, // Default security
OPEN_EXISTING, // Existing file only
FILE_ATTRIBUTE_NORMAL, // Normal file
NULL);
if (hFile == INVALID_HANDLE_VALUE)
{
wprintf(L"open file failed: %d\n", GetLastError());
SET_FAILURE_AND_CLEANUP;
}

// open an algorithm handle
if (!NT_SUCCESS(status = BCryptOpenAlgorithmProvider(
&hAlg,
BCRYPT_SHA256_ALGORITHM,
NULL,
0)))
{
wprintf(L"open an algorithm handle failed: %x\n", status);
SET_FAILURE_AND_CLEANUP;
}

// calculate the size of the buffer to hold the hash object
if (!NT_SUCCESS(status = BCryptGetProperty(
hAlg,
BCRYPT_OBJECT_LENGTH,
(PBYTE)&cbHashObject,
sizeof(DWORD),
&cbData,
0)))
{
wprintf(L"hash buffer size allocation failed, err: %x\n", status);
SET_FAILURE_AND_CLEANUP;
}

// allocate the hash object on the heap
pbHashObject = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHashObject);
if (NULL == pbHashObject)
{
wprintf(L"memory allocation for hash object failed\n");
SET_FAILURE_AND_CLEANUP;
}

// calculate the length of the hash
if (!NT_SUCCESS(status = BCryptGetProperty(
hAlg,
BCRYPT_HASH_LENGTH,
(PBYTE)&cbHash,
sizeof(DWORD),
&cbData,
0)))
// just print checksum
if (shasums_file == NULL)
{
wprintf(L"hash length calculation failed: %x\n", status);
SET_FAILURE_AND_CLEANUP;
}

// allocate the hash buffer on the heap
pbHash = (PBYTE)HeapAlloc(GetProcessHeap(), 0, cbHash);
if (NULL == pbHash)
{
wprintf(L"memory allocation for hash buffer failed\n");
SET_FAILURE_AND_CLEANUP;
}

// create a hash
if (!NT_SUCCESS(status = BCryptCreateHash(
hAlg,
&hHash,
pbHashObject,
cbHashObject,
NULL,
0,
0)))
{
wprintf(L"hash creation failed: %x\n", status);
SET_FAILURE_AND_CLEANUP;
}

while (TRUE)
{
if (!ReadFile(hFile, buffer, sizeof(buffer), &dwBytesRead, NULL))
wchar_t *file_hash = calc_hash(argv[1]);
if (file_hash != NULL)
{
wprintf(L"read file failed: %d\n", GetLastError());
SET_FAILURE_AND_CLEANUP;
}

if (dwBytesRead == 0)
{
break;
}

// hash some data
if (!NT_SUCCESS(status = BCryptHashData(
hHash,
(PBYTE)buffer,
dwBytesRead,
0)))
{
wprintf(L"data hashing failed: %x\n", status);
SET_FAILURE_AND_CLEANUP;
wprintf(L"%ls %ls\n", file_hash, argv[1]);
}
}

// close the hash
if (!NT_SUCCESS(status = BCryptFinishHash(
hHash,
pbHash,
cbHash,
0)))
// check SHASUMS
else
{
wprintf(L"hash finalization failed: %x\n", status);
SET_FAILURE_AND_CLEANUP;
wprintf(L"to be implemented");
}

// Output the hash
for (DWORD i = 0; i < cbHash; i++)
{
printf("%02x", pbHash[i]);
}

Cleanup:

if (hFile)
{
CloseHandle(hFile);
}

if (hAlg)
{
BCryptCloseAlgorithmProvider(hAlg, 0);
}

if (hHash)
{
BCryptDestroyHash(hHash);
}

if (pbHashObject)
{
HeapFree(GetProcessHeap(), 0, pbHashObject);
}

if (pbHash)
{
HeapFree(GetProcessHeap(), 0, pbHash);
}

return failure;
}
Loading

0 comments on commit 4274ca9

Please sign in to comment.