Любые идеи о том, как я могу исправить это?
Код: Выделить всё
#include
#include
#include // For malloc, realloc, free
#include
#include // For wcslen and wcscpy
HANDLE hNewFileItemEvent;
HANDLE hNewSearchItemEvent;
HANDLE hNoMoreWorkEvent;
WCHAR* filePath;
WIN32_FIND_DATAW fd;
WCHAR subPath[MAX_PATH];
const WCHAR* rootPath = L"D:\\search";
CRITICAL_SECTION g_queueCS;
typedef struct {
WCHAR** data; // Pointer to an array of string pointers
int size; // Current number of strings in the array
int capacity; // Allocated capacity of the array
} StringDynamicArray;
StringDynamicArray myFolders;
StringDynamicArray myFiles;
void initStringDynamicArray(StringDynamicArray* arr, int initialCapacity) {
arr->data = (WCHAR**)malloc(sizeof(WCHAR*) * initialCapacity);
if (arr->data == NULL) {
perror("Failed to allocate initial memory for string array");
exit(EXIT_FAILURE);
}
arr->size = 0;
arr->capacity = initialCapacity;
}
void pushString(StringDynamicArray* arr, const WCHAR* str) {
if (arr->size == arr->capacity) {
arr->capacity *= 2;
arr->data = (WCHAR**)realloc(arr->data, sizeof(WCHAR*) * arr->capacity);
if (arr->data == NULL) {
perror("Failed to reallocate memory for string array");
exit(EXIT_FAILURE);
}
}
size_t strLen = wcslen(str);
arr->data[arr->size] = (WCHAR*)malloc((strLen + 1) * sizeof(wchar_t)); // +1 for null terminator
if (arr->data[arr->size] == NULL) {
perror("Failed to allocate memory for string");
exit(EXIT_FAILURE);
}
// Use wcscpy_s with the correct buffer size (strLen + 1)
errno_t err = wcscpy_s(arr->data[arr->size], strLen + 1, str);
if (err == 0) {
wprintf(L"Successfully copied: %ls\n", arr->data[arr->size]);
arr->size++;
}
else {
wprintf(L"Error copying string. Error code: %d\n", err);
}
}
WCHAR* popString(StringDynamicArray* arr) {
if (arr->size == 0) {
fprintf(stderr, "Error: Cannot pop from an empty array.\n");
return NULL;
}
arr->size--;
WCHAR* poppedStr = arr->data[arr->size];
return poppedStr; // Caller is responsible for freeing this memory
}
void freeStringDynamicArray(StringDynamicArray* arr) {
for (int i = 0; i < arr->size; i++) {
free(arr->data[i]); // Free individual strings
}
free(arr->data); // Free the array of pointers
arr->data = NULL;
arr->size = 0;
arr->capacity = 0;
}
void searchDirectories(const WCHAR* path) {
WIN32_FIND_DATAW findData;
HANDLE hFind = INVALID_HANDLE_VALUE;
WCHAR searchPath[MAX_PATH];
WCHAR subPath[MAX_PATH];
// Construct the search pattern (e.g., "D:\\search\\*")
swprintf_s(searchPath, MAX_PATH, L"%s\\*", path);
// Start the search with FindFirstFileW
hFind = FindFirstFileW(searchPath, &findData);
if (hFind == INVALID_HANDLE_VALUE) {
wprintf(L"Error opening directory %s: %d\n", path, GetLastError());
return;
}
// Iterate through all files and directories
do {
// Skip the current (".") and parent ("..") directories
if (wcscmp(findData.cFileName, L".") == 0 || wcscmp(findData.cFileName, L"..") == 0) {
continue;
}
// Construct the full path of the current file or directory
swprintf_s(subPath, MAX_PATH, L"%s\\%s", path, findData.cFileName);
// Print the full path
wprintf(L"%s\n", subPath);
// If it's a directory, recursively search it
if (findData.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) {
pushString(&myFolders, (LPCWSTR)subPath);
searchDirectories(subPath);
}
} while (FindNextFileW(hFind, &findData) != 0);
// Check if the loop ended due to an error
DWORD error = GetLastError();
if (error != ERROR_NO_MORE_FILES) {
wprintf(L"Error during directory search: %d\n", error);
}
// Close the search handle
FindClose(hFind);
}
//IN each directory provided as an argument search for all files in it
void searchFiles(const WCHAR* path) {
WIN32_FIND_DATAW findData;
HANDLE hFind = INVALID_HANDLE_VALUE;
WCHAR searchPath[MAX_PATH];
WCHAR subPath[MAX_PATH];
swprintf_s(searchPath, MAX_PATH, L"%s\\*", path);
// Start the search with FindFirstFileW
hFind = FindFirstFileW(searchPath, &findData);
if (hFind == INVALID_HANDLE_VALUE) {
wprintf(L"Error opening directory %s: %d\n", path, GetLastError());
return;
}
// Iterate through all files and directories
do {
// Skip the current (".") and parent ("..") directories
if (wcscmp(findData.cFileName, L".") == 0 || wcscmp(findData.cFileName, L"..") == 0) {
continue;
}
// Construct the full path of the current file or directory
swprintf_s(subPath, MAX_PATH, L"%s\\%s", path, findData.cFileName);
// Print the full path
wprintf(L"%s\n", subPath);
// If it's NOT a directory, write it to the myFiles Struct
if (findData.dwFileAttributes != FILE_ATTRIBUTE_DIRECTORY) {
::EnterCriticalSection(&g_queueCS);
printf("Size: %d\n", myFiles.size);
pushString(&myFiles, (LPCWSTR)subPath);
::LeaveCriticalSection(&g_queueCS);
::SetEvent(hNewSearchItemEvent);
}
} while (FindNextFileW(hFind, &findData) != 0);
// Check if the loop ended due to an error
DWORD error = GetLastError();
if (error != ERROR_NO_MORE_FILES) {
wprintf(L"Error during directory search: %d\n", error);
}
// Close the search handle
FindClose(hFind);
}
BOOL FileMatchesSearch(WCHAR fullPath[], WCHAR targetString[]) {
size_t fullPathLen = wcslen(fullPath);
size_t targetStringLen = wcslen(targetString);
// Check if the full path is long enough to contain the target string
if (fullPathLen >= targetStringLen) {
// Get a pointer to the potential start of the target string in fullPath
WCHAR* endOfPath = fullPath + (fullPathLen - targetStringLen);
// Compare the substring with the target string
if (wcscmp(endOfPath, targetString) == 0) {
//printf("'%ws' exists at the end of the path.\n", targetString);
printf("File path found: %ws\n", fullPath);
return TRUE;
}
else {
printf("'%ws' does NOT exist at the end of the path.\n", targetString);
return FALSE;
}
}
else {
printf("The path is too short to contain '%ws'.\n", targetString);
return FALSE;
}
}
DWORD WINAPI FolderThread(PVOID) {
searchDirectories(rootPath);
::SetEvent(hNewFileItemEvent);
return 42;
}
DWORD WINAPI FileThread(LPVOID lpParam) {
const WCHAR* folderPath = (WCHAR*)lpParam;
wprintf(L"Processing string: %s\n", folderPath);
while (true) {
HANDLE waitHandles[2] = { hNewFileItemEvent, hNoMoreWorkEvent };
DWORD waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 1) { // hNoMoreWorkEvent is signaled
return 0; // Exit the thread
}
else {
break;
}
}
searchFiles(folderPath);
return 42;
}
DWORD WINAPI SearchThread(PVOID) {
while (true) {
HANDLE waitHandles[2] = { hNewSearchItemEvent, hNoMoreWorkEvent };
DWORD waitResult = WaitForMultipleObjects(2, waitHandles, FALSE, INFINITE);
if (waitResult == WAIT_OBJECT_0 + 1) { // hNoMoreWorkEvent is signaled
break; // Exit the thread
}
// Else, hNewItemEvent was signaled. Grab work.
//Sleep(10000);
::EnterCriticalSection(&g_queueCS);
if (myFiles.size != 0) {
filePath = popString(&myFiles);
// If we just took the last item, reset the event
}
else if (myFiles.size == 0) {
::ResetEvent(hNewSearchItemEvent);
}
::LeaveCriticalSection(&g_queueCS);
WCHAR searchPattern[] = L"My_search_item.txt";
// Allocate a WCHAR array on the stack, including space for the null terminator
const int MAX_LENGTH = 256; // Or a suitable maximum length
WCHAR destinationArray[MAX_LENGTH];
// Copy the string
wcscpy_s(destinationArray, MAX_LENGTH, filePath);
if (FileMatchesSearch(destinationArray, searchPattern)) {
printf("File Found...!!!\n");
}
}
return 0;
}
int main()
{
::InitializeCriticalSection(&g_queueCS);
initStringDynamicArray(&myFolders, 5);
initStringDynamicArray(&myFiles, 5);
// Create a manual-reset event in a non-signaled state
hNewFileItemEvent = ::CreateEvent(
NULL, // Default security attributes
TRUE, // Manual-reset event
FALSE, // Initial state is non-signaled
L"NewItemEvent" // Name of the event (optional)
);
// Create a manual-reset event in a non-signaled state
hNewSearchItemEvent = ::CreateEvent(
NULL, // Default security attributes
TRUE, // Manual-reset event
FALSE, // Initial state is non-signaled
L"NewItemEvent" // Name of the event (optional)
);
// Create a manual-reset event in a non-signaled state
hNoMoreWorkEvent = ::CreateEvent(
NULL, // Default security attributes
TRUE, // Manual-reset event
FALSE, // Initial state is non-signaled
L"NewItemEvent" // Name of the event (optional)
);
//************************Folder thread
HANDLE hThreadFolder = ::CreateThread(NULL,0, FolderThread, NULL, 0 ,NULL);
::WaitForSingleObject(hThreadFolder, INFINITE);
// Array to store thread handles
HANDLE* threads = (HANDLE*)malloc(myFolders.size * sizeof(HANDLE));
if (!threads) {
wprintf(L"Failed to allocate memory for thread handles\n");
return 1;
}
//**************MULtiple threads to look for files in each folder discovered (One thread per folder)
// Loop through the data array and create a thread for each index
for (int i = 0; i < myFolders.size; i++) {
threads[i] = CreateThread(
NULL, // Default security attributes
0, // Default stack size
FileThread, // Thread function
myFolders.data[i], // Pass the string at index i
0, // Default creation flags
NULL // No thread ID needed
);
if (threads[i] == NULL) {
wprintf(L"Failed to create thread for index %d\n", i);
// Handle error (e.g., clean up and exit)
}
}
// Wait for all threads to complete
WaitForMultipleObjects(myFolders.size, threads, TRUE, INFINITE);
// ****************************Singe thread to Search for the File by file name
HANDLE hThreadSearch = ::CreateThread(NULL, 0, SearchThread, NULL, 0, NULL);
::WaitForSingleObject(hThreadSearch, INFINITE);
// Clean up thread handles
for (int i = 0; i < myFolders.size; i++) {
if (threads[i]) {
CloseHandle(threads[i]);
}
}
// Clean up allocated memory
for (int i = 0; i < myFolders.size; i++) {
free(myFolders.data[i]); // Free each string
}
free(myFolders.data); // Free the array of pointers
free(threads); // Free thread handles array
::CloseHandle(hThreadFolder);
::CloseHandle(hThreadSearch);
::DeleteCriticalSection(&g_queueCS);
freeStringDynamicArray(&myFolders);
freeStringDynamicArray(&myFiles);
return 0;
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... working-as