244 lines
6.7 KiB
Plaintext
244 lines
6.7 KiB
Plaintext
#include <windows.h>
|
|
#include <stdio.h>
|
|
#include <string.h>
|
|
#include <stdlib.h>
|
|
|
|
#define BUFFER_SIZE 4096
|
|
#define MAX_LINE_LENGTH 1024
|
|
|
|
typedef struct {
|
|
DWORD attributes;
|
|
FILETIME creationTime;
|
|
FILETIME lastAccessTime;
|
|
FILETIME lastWriteTime;
|
|
DWORD fileSizeHigh;
|
|
DWORD fileSizeLow;
|
|
} FileAttributes;
|
|
|
|
void splitString(const char* str, char*** lines, int* lineCount) {
|
|
*lineCount = 0;
|
|
*lines = NULL;
|
|
|
|
const char* start = str;
|
|
const char* current = str;
|
|
|
|
while (*current) {
|
|
if (*current == '\r' || *current == '\n') {
|
|
size_t length = current - start;
|
|
if (length > 0) {
|
|
*lines = realloc(*lines, (*lineCount + 1) * sizeof(char*));
|
|
(*lines)[*lineCount] = malloc(length + 1);
|
|
strncpy((*lines)[*lineCount], start, length);
|
|
(*lines)[*lineCount][length] = '\0';
|
|
(*lineCount)++;
|
|
}
|
|
|
|
if (*current == '\r' && *(current + 1) == '\n') {
|
|
current++;
|
|
}
|
|
|
|
start = current + 1;
|
|
}
|
|
current++;
|
|
}
|
|
|
|
size_t remaining = current - start;
|
|
if (remaining > 0) {
|
|
*lines = realloc(*lines, (*lineCount + 1) * sizeof(char*));
|
|
(*lines)[*lineCount] = malloc(remaining + 1);
|
|
strncpy((*lines)[*lineCount], start, remaining);
|
|
(*lines)[*lineCount][remaining] = '\0';
|
|
(*lineCount)++;
|
|
}
|
|
}
|
|
|
|
void freeLines(char** lines, int lineCount) {
|
|
for (int i = 0; i < lineCount; i++) {
|
|
free(lines[i]);
|
|
}
|
|
free(lines);
|
|
}
|
|
|
|
char* fileTimeToString(const FILETIME* ft) {
|
|
if (ft->dwLowDateTime == 0 && ft->dwHighDateTime == 0) {
|
|
return strdup("N/A");
|
|
}
|
|
|
|
SYSTEMTIME st;
|
|
FileTimeToSystemTime(ft, &st);
|
|
|
|
char* buffer = malloc(64);
|
|
snprintf(buffer, 64, "%02d.%02d.%04d %02d:%02d:%02d",
|
|
st.wDay, st.wMonth, st.wYear,
|
|
st.wHour, st.wMinute, st.wSecond);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
char* attributesToString(DWORD attrs) {
|
|
if (attrs == INVALID_FILE_ATTRIBUTES) {
|
|
return strdup("Invalid attributes");
|
|
}
|
|
|
|
char* result = calloc(256, 1);
|
|
int first = 1;
|
|
|
|
#define ADD_ATTR(attr, name) \
|
|
if (attrs & attr) { \
|
|
if (!first) strcat(result, ", "); \
|
|
strcat(result, name); \
|
|
first = 0; \
|
|
}
|
|
|
|
ADD_ATTR(FILE_ATTRIBUTE_ARCHIVE, "Archive");
|
|
ADD_ATTR(FILE_ATTRIBUTE_COMPRESSED, "Compressed");
|
|
ADD_ATTR(FILE_ATTRIBUTE_DIRECTORY, "Directory");
|
|
ADD_ATTR(FILE_ATTRIBUTE_ENCRYPTED, "Encrypted");
|
|
ADD_ATTR(FILE_ATTRIBUTE_HIDDEN, "Hidden");
|
|
ADD_ATTR(FILE_ATTRIBUTE_NORMAL, "Normal");
|
|
ADD_ATTR(FILE_ATTRIBUTE_OFFLINE, "Offline");
|
|
ADD_ATTR(FILE_ATTRIBUTE_READONLY, "Readonly");
|
|
ADD_ATTR(FILE_ATTRIBUTE_SYSTEM, "System");
|
|
ADD_ATTR(FILE_ATTRIBUTE_TEMPORARY, "Temporary");
|
|
|
|
#undef ADD_ATTR
|
|
|
|
return result;
|
|
}
|
|
|
|
FileAttributes getFileAttributesWin(const char* filePath) {
|
|
FileAttributes attrs = {0};
|
|
WIN32_FILE_ATTRIBUTE_DATA fileInfo;
|
|
|
|
if (GetFileAttributesExA(filePath, GetFileExInfoStandard, &fileInfo)) {
|
|
attrs.attributes = fileInfo.dwFileAttributes;
|
|
attrs.creationTime = fileInfo.ftCreationTime;
|
|
attrs.lastAccessTime = fileInfo.ftLastAccessTime;
|
|
attrs.lastWriteTime = fileInfo.ftLastWriteTime;
|
|
attrs.fileSizeHigh = fileInfo.nFileSizeHigh;
|
|
attrs.fileSizeLow = fileInfo.nFileSizeLow;
|
|
} else {
|
|
attrs.attributes = INVALID_FILE_ATTRIBUTES;
|
|
}
|
|
|
|
return attrs;
|
|
}
|
|
|
|
void runChildProcess(const char* handleStr) {
|
|
printf("Child process started.\n");
|
|
|
|
HANDLE hFile = (HANDLE)(INT_PTR)atoll(handleStr);
|
|
char buffer[BUFFER_SIZE];
|
|
DWORD bytesRead;
|
|
char* totalData = calloc(1, 1);
|
|
size_t totalSize = 0;
|
|
|
|
while (ReadFile(hFile, buffer, sizeof(buffer), &bytesRead, NULL) && bytesRead > 0) {
|
|
totalData = realloc(totalData, totalSize + bytesRead + 1);
|
|
memcpy(totalData + totalSize, buffer, bytesRead);
|
|
totalSize += bytesRead;
|
|
totalData[totalSize] = '\0';
|
|
}
|
|
|
|
CloseHandle(hFile);
|
|
|
|
char** lines = NULL;
|
|
int lineCount = 0;
|
|
splitString(totalData, &lines, &lineCount);
|
|
free(totalData);
|
|
|
|
for (int i = 0; i < lineCount; i++) {
|
|
if (strlen(lines[i]) == 0) continue;
|
|
|
|
FileAttributes attrs = getFileAttributesWin(lines[i]);
|
|
ULONGLONG fileSize = ((ULONGLONG)attrs.fileSizeHigh << 32) | attrs.fileSizeLow;
|
|
|
|
char* attrStr = attributesToString(attrs.attributes);
|
|
char* createdStr = fileTimeToString(&attrs.creationTime);
|
|
char* accessedStr = fileTimeToString(&attrs.lastAccessTime);
|
|
char* modifiedStr = fileTimeToString(&attrs.lastWriteTime);
|
|
|
|
printf("\nFile: %s\n", lines[i]);
|
|
printf("Attributes: %s\n", attrStr);
|
|
printf("Size: %llu bytes\n", fileSize);
|
|
printf("Created: %s\n", createdStr);
|
|
printf("Last accessed: %s\n", accessedStr);
|
|
printf("Last modified: %s\n", modifiedStr);
|
|
|
|
free(attrStr);
|
|
free(createdStr);
|
|
free(accessedStr);
|
|
free(modifiedStr);
|
|
}
|
|
|
|
freeLines(lines, lineCount);
|
|
}
|
|
|
|
void runParentProcess() {
|
|
printf("Parent process started.\n");
|
|
|
|
SECURITY_ATTRIBUTES sa = {0};
|
|
sa.nLength = sizeof(SECURITY_ATTRIBUTES);
|
|
sa.bInheritHandle = FALSE;
|
|
|
|
HANDLE hFile = CreateFileA(
|
|
"test.txt",
|
|
GENERIC_READ,
|
|
FILE_SHARE_READ,
|
|
&sa,
|
|
OPEN_EXISTING,
|
|
FILE_ATTRIBUTE_NORMAL,
|
|
NULL
|
|
);
|
|
|
|
if (hFile == INVALID_HANDLE_VALUE) {
|
|
fprintf(stderr, "Error opening file. Error: %lu\n", GetLastError());
|
|
return;
|
|
}
|
|
|
|
if (!SetHandleInformation(hFile, HANDLE_FLAG_INHERIT, HANDLE_FLAG_INHERIT)) {
|
|
fprintf(stderr, "Failed to set handle inheritance. Error: %lu\n", GetLastError());
|
|
CloseHandle(hFile);
|
|
return;
|
|
}
|
|
|
|
char cmdLine[256];
|
|
snprintf(cmdLine, sizeof(cmdLine), "%s child %lld", GetCommandLineA(), (long long)(INT_PTR)hFile);
|
|
|
|
STARTUPINFOA si = {0};
|
|
si.cb = sizeof(si);
|
|
PROCESS_INFORMATION pi = {0};
|
|
|
|
if (!CreateProcessA(
|
|
NULL,
|
|
cmdLine,
|
|
NULL,
|
|
NULL,
|
|
TRUE,
|
|
0,
|
|
NULL,
|
|
NULL,
|
|
&si,
|
|
&pi)) {
|
|
fprintf(stderr, "Error creating child process. Error: %lu\n", GetLastError());
|
|
CloseHandle(hFile);
|
|
return;
|
|
}
|
|
|
|
CloseHandle(pi.hProcess);
|
|
CloseHandle(pi.hThread);
|
|
CloseHandle(hFile);
|
|
}
|
|
|
|
int main(int argc, char* argv[]) {
|
|
if (argc == 1) {
|
|
runParentProcess();
|
|
} else if (argc == 3 && strcmp(argv[1], "child") == 0) {
|
|
runChildProcess(argv[2]);
|
|
} else {
|
|
fprintf(stderr, "Invalid arguments.\n");
|
|
return 1;
|
|
}
|
|
|
|
return 0;
|
|
} |