79753622

Date: 2025-09-02 14:49:00
Score: 0.5
Natty:
Report link

Hi there finally I have it working, first of all there were several errors in my code the event objects were using the same name (In my working code example only one event object was necessary). also I had to make several other changes as well.

#include <Windows.h>
#include <stdio.h>
#include <stdlib.h> // For malloc, realloc, free
#include <string.h>
#include <wchar.h> // For wcslen and wcscpy
HANDLE g_NewFileItemEvent;
HANDLE g_NoMoreWorkEvent;
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];
    //::EnterCriticalSection(&g_queueCS);
    //pushString(&myFolders, (LPCWSTR)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) {
            wprintf(L"[DIR]: %ws\n", subPath);
            pushString(&myFolders, (LPCWSTR)subPath);
            searchDirectories(subPath);
        }
        
    } while (FindNextFileW(hFind, &findData) != 0);
    //::LeaveCriticalSection(&g_queueCS);
    // 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
    while (FindNextFileW(hFind, &findData) != 0) {
        // 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) {
            //wprintf(L"[FILE]: %s\n", subPath);
            ::EnterCriticalSection(&g_queueCS);
            //printf("Size: %d\n", myFiles.size);
            pushString(&myFiles, (LPCWSTR)subPath);
            ::LeaveCriticalSection(&g_queueCS);
        }
    }
    printf("File thread: Finished producing items.\n");
    
    // 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);
    ::Sleep(20000);
    ::SetEvent(g_NewFileItemEvent);
    return 42;
}
DWORD WINAPI FileThread(LPVOID lpParam) {
    printf("File thread: waiting for Start signal.\n");
    ::WaitForSingleObject(g_NewFileItemEvent, INFINITE);
    const WCHAR* folderPath = (WCHAR*)lpParam;
    wprintf(L"Processing string: %s\n", folderPath);
    printf("File thread: Starting.\n");
    searchFiles(folderPath);
    printf("File thread: Exiting.\n");
    return 42;
}
DWORD WINAPI SearchThread(PVOID) {
    printf("Search thread started. Waiting for manual reset event...\n");
    // Wait for the manual reset event
    WaitForSingleObject(g_NewFileItemEvent, INFINITE);
    printf("Search thread: Event received! Starting to consume items...\n");
    while (myFiles.size !=0) {
        ::EnterCriticalSection(&g_queueCS);
        WCHAR* filePath = NULL;
        if (myFiles.size != 0)
        {
            filePath = popString(&myFiles);
            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");
            }
        }
        ::LeaveCriticalSection(&g_queueCS);
    }
    printf("Search thread: Thread exiting.\n");
    return 42;
}
int main(){
    ::InitializeCriticalSection(&g_queueCS);
    initStringDynamicArray(&myFolders, 5);
    initStringDynamicArray(&myFiles, 5);
    pushString(&myFolders, rootPath);//Without this Line it won't search in the current folder
    // Create a manual-reset event in a non-signaled state
    g_NewFileItemEvent = ::CreateEvent(
        NULL,               // Default security attributes
        TRUE,               // Manual-reset event
        FALSE,              // Initial state is non-signaled
        L"NewFileItemEvent" // 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]);
        }
    }
    free(threads); // Free thread handles array
    ::CloseHandle(hThreadFolder);
    ::CloseHandle(hThreadSearch);
    ::DeleteCriticalSection(&g_queueCS);
    freeStringDynamicArray(&myFolders);
    freeStringDynamicArray(&myFiles);
    return 0;
}
Reasons:
  • Blacklisted phrase (0.5): Hi there
  • Long answer (-1):
  • Has code block (-0.5):
  • Self-answer (0.5):
  • Low reputation (1):
Posted by: user6033723