Пример #1
0
VOID SCALL LogFileFormatV(const CHAR *format, va_list argList)
{
    DWORD       errorCode;
    LOG_ENTRY   *entry;
    size_t      remaining;

    // Preserve system error code
    errorCode = GetLastError();

    ASSERT(format != NULL);

    // Retrieve a spare entry structure (also checks log status)
    entry = GetSpareEntry();
    if (entry != NULL) {
        GetLocalTime(&entry->time);

        StringCchVPrintfExA(entry->message, ELEMENT_COUNT(entry->message),
            NULL, &remaining, 0, format, argList);

        entry->length = ELEMENT_COUNT(entry->message) - remaining;

        // Insert log entry into the write queue
        QueueInsert(entry);
    }

    // Restore system error code
    SetLastError(errorCode);
}
Пример #2
0
VOID SCALL LogFileTraceV(const CHAR *file, const CHAR *func, INT line, const CHAR *format, va_list argList)
{
#if 0
    CHAR        location[MAX_PATH];
#endif
    CHAR        *messageEnd;
    DWORD       errorCode;
    DWORD       processId;
    DWORD       threadId;
    LOG_ENTRY   *entry;
    size_t      remaining;

    // Preserve system error code
    errorCode = GetLastError();

    ASSERT(file != NULL);
    ASSERT(func != NULL);
    ASSERT(format != NULL);

    processId = GetCurrentProcessId();
    threadId  = GetCurrentThreadId();

    // Retrieve a spare entry structure (also checks log status)
    entry = GetSpareEntry();
    if (entry != NULL) {
        //
        // Available trace information:
        //
        // file      - Source file
        // func      - Function name in the source file
        // line      - Line number in the source file
        // processId - Current process ID
        // threadId  - Current thread ID
        //
        GetLocalTime(&entry->time);

#if 0
        StringCchPrintfA(location, ELEMENT_COUNT(location), "%s:%d", LogFileName(file), line);

        StringCchPrintfExA(entry->message, ELEMENT_COUNT(entry->message),
            &messageEnd, &remaining, 0, "%-20s - %-20s - ", location, func);
#else
        StringCchPrintfExA(entry->message, ELEMENT_COUNT(entry->message),
            &messageEnd, &remaining, 0, "%s - ", func);
#endif
        StringCchVPrintfExA(messageEnd, remaining, NULL, &remaining, 0, format, argList);

        entry->length = ELEMENT_COUNT(entry->message) - remaining;

        // Insert log entry into the write queue
        QueueInsert(entry);
    }

    // Restore system error code
    SetLastError(errorCode);
}
Пример #3
0
void test_different_lists(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 2, 3 };
   int base_list[] = { 2, 3, 4 };

   TEST_ASSERT_EQUAL(UNEQUAL,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #4
0
void test_order_matters_to_a_list(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 2, 3 };
   int base_list[] = { 3, 2, 1 };

   TEST_ASSERT_EQUAL(UNEQUAL,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #5
0
void test_false_start(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 2, 5 };
   int base_list[] = { 0, 1, 2, 3, 1, 2, 5, 6 };

   TEST_ASSERT_EQUAL(SUBLIST,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #6
0
void test_second_list_missing_element_from_first_list(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 2, 3 };
   int base_list[] = { 1, 3 };

   TEST_ASSERT_EQUAL(UNEQUAL,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #7
0
void test_at_end_of_superlist(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 0, 1, 2, 3, 4, 5 };
   int base_list[] = { 3, 4, 5 };

   TEST_ASSERT_EQUAL(SUPERLIST,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #8
0
void test_consecutive(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 1, 2 };
   int base_list[] = { 0, 1, 1, 1, 2, 1, 2 };

   TEST_ASSERT_EQUAL(SUBLIST,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #9
0
void test_sublist_at_middle(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 2, 3, 4 };
   int base_list[] = { 0, 1, 2, 3, 4, 5 };

   TEST_ASSERT_EQUAL(SUBLIST,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #10
0
void test_list_equals_itself(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 2, 3 };
   int base_list[] = { 1, 2, 3 };

   TEST_ASSERT_EQUAL(EQUAL,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #11
0
void test_same_digits_but_different_numbers(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 0, 1 };
   int base_list[] = { 10, 1 };

   TEST_ASSERT_EQUAL(UNEQUAL,
                     check_lists(list_to_compare, base_list,
                                 ELEMENT_COUNT(list_to_compare),
                                 ELEMENT_COUNT(base_list)));
}
Пример #12
0
static VOID CCALL QueueWrite(VOID *context)
{
    CHAR        buffer[128];
    DWORD       written;
    HANDLE      file;
    LOG_ENTRY   *entry;
    size_t      remaining;

    UNREFERENCED_PARAMETER(context);

    // Log system must be inactive or shutting down (flush)
    if (logStatus != LOG_STATUS_ACTIVE && logStatus != LOG_STATUS_SHUTDOWN) {
        return;
    }

    file = FileOpen(logPath, GENERIC_WRITE, FILE_SHARE_READ, 10);
    if (file == INVALID_HANDLE_VALUE) {
        return;
    }

    // Process all queued log entries
    for (;;) {
        entry = GetQueueEntry();
        if (entry == NULL) {
            break;
        }

        // Format the time stamp
        StringCchPrintfExA(buffer, ELEMENT_COUNT(buffer), NULL, &remaining, 0,
            "%02d-%02d-%04d %02d:%02d:%02d ",
            entry->time.wMonth, entry->time.wDay, entry->time.wYear,
            entry->time.wHour, entry->time.wMinute, entry->time.wSecond);

        // Seek to the end of the log file
        SetFilePointer(file, 0, 0, FILE_END);

        if (!WriteFile(file, buffer, ELEMENT_COUNT(buffer) - remaining, &written, NULL)) {
            TRACE("Unable to write log file (error %lu).", GetLastError());
        }
        if (!WriteFile(file, entry->message, entry->length, &written, NULL)) {
            TRACE("Unable to write log file (error %lu).", GetLastError());
        }

        MemFree(entry);
    }

    CloseHandle(file);
}
Пример #13
0
/*++

TraceFormat

    Sends the message to a debugger.

Arguments:
    funct   - Pointer to a null-terminated string that specifies the function.

    format  - Pointer to a null-terminated printf-style format string.

    ...     - Arguments to insert into "format".

Return Values:
    None.

--*/
VOID CCALL TraceFormat(const char *funct, const char *format, ...)
{
    char *end;
    char output[1024];
    DWORD error;
    size_t remaining;
    va_list argList;

    ASSERT(funct != NULL);
    ASSERT(format != NULL);

    // Preserve system error code
    error = GetLastError();

    StringCchPrintfExA(output, ELEMENT_COUNT(output), &end, &remaining, 0,
        "| %4d | %17s | ", GetCurrentThreadId(), funct);
    va_start(argList, format);
    StringCchVPrintfA(end, remaining, format, argList);
    va_end(argList);

    OutputDebugStringA(output);

    // Restore system error code
    SetLastError(error);
}
Пример #14
0
DWORD FileGroupDelete(INT32 groupId)
{
    CHAR    *path;
    CHAR    buffer[12];
    DWORD   result;

    ASSERT(groupId != -1);
    TRACE("groupId=%d", groupId);

    // Retrieve group file location
    StringCchPrintfA(buffer, ELEMENT_COUNT(buffer), "%i", groupId);
    path = Io_ConfigGetPath("Locations", "Group_Files", buffer, NULL);
    if (path == NULL) {
        TRACE("Unable to retrieve file location.");
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    // Delete group file and free resources
    if (DeleteFileA(path)) {
        result = ERROR_SUCCESS;
    } else {
        result = GetLastError();
        TRACE("Unable to delete file \"%s\" (error %lu).", path, result);
    }

    Io_Free(path);
    return result;
}
Пример #15
0
/*++

ConnectionClose

    Closes the server connection.

Arguments:
    context - Opaque context passed to <PoolCreate>.

    data    - Pointer to the DB_CONTEXT structure.

Return Values:
    None.

--*/
static VOID FCALL ConnectionClose(VOID *context, VOID *data)
{
    DB_CONTEXT  *db = data;
    DWORD       i;

    UNREFERENCED_PARAMETER(context);
    ASSERT(data != NULL);
    TRACE("context=%p data=%p", context, data);

    // Free pre-compiled statement structures
    for (i = 0; i < ELEMENT_COUNT(db->stmt); i++) {
        if (db->stmt[i] != NULL) {
            mysql_stmt_close(db->stmt[i]);
        }
    }

    // Free handle structure
    if (db->handle != NULL) {
        mysql_close(db->handle);
    }

    // Free context structure
    ZeroMemory(db, sizeof(DB_CONTEXT));
    MemFree(db);
}
Пример #16
0
void test_empty_list_within_non_empty_list(void)
{
   TEST_IGNORE();               // delete this line to run test
   int base_list[] = { 1, 2, 3 };

   TEST_ASSERT_EQUAL(SUBLIST,
                     check_lists(NULL, base_list, 0, ELEMENT_COUNT(base_list)));
}
Пример #17
0
void test_non_empty_list_contains_empty_list(void)
{
   TEST_IGNORE();
   int list_to_compare[] = { 1, 2, 3 };

   TEST_ASSERT_EQUAL(SUPERLIST,
                     check_lists(list_to_compare, NULL,
                                 ELEMENT_COUNT(list_to_compare), 0));
}
Пример #18
0
DWORD FileGroupCreate(INT32 groupId, GROUPFILE *groupFile)
{
    CHAR   *defaultPath = NULL;
    CHAR   *targetPath = NULL;
    CHAR   buffer[12];
    DWORD  result = ERROR_SUCCESS;

    ASSERT(groupId != -1);
    ASSERT(groupFile != NULL);
    TRACE("groupId=%d groupFile=%p", groupId, groupFile);

    // Retrieve default location
    defaultPath = Io_ConfigGetPath("Locations", "Group_Files", "Default.Group", NULL);
    if (defaultPath == NULL) {
        TRACE("Unable to retrieve default file location.");
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    // Retrieve target location
    StringCchPrintfA(buffer, ELEMENT_COUNT(buffer), "%i", groupId);
    targetPath = Io_ConfigGetPath("Locations", "Group_Files", buffer, NULL);
    if (targetPath == NULL) {
        TRACE("Unable to retrieve group file location.");

        Io_Free(defaultPath);
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    // Copy default file to target file
    if (!CopyFileA(defaultPath, targetPath, FALSE)) {
        result = GetLastError();
        TRACE("Unable to copy file \"%s\" to \"%s\" (error %lu).",
            defaultPath, targetPath, result);
    } else {

        // Open new group file
        result = FileGroupOpen(groupId, groupFile);
        if (result != ERROR_SUCCESS) {
            TRACE("Unable to open group file (error %lu).", result);
        }
    }

    Io_Free(defaultPath);
    Io_Free(targetPath);

    return result;
}
Пример #19
0
DWORD FileGroupOpen(INT32 groupId, GROUPFILE *groupFile)
{
    CHAR        buffer[12];
    CHAR        *path;
    DWORD       result;
    MOD_CONTEXT *mod;

    ASSERT(groupId != -1);
    ASSERT(groupFile != NULL);
    TRACE("groupId=%d groupFile=%p", groupId, groupFile);

    // Check if ioFTPD wiped out the module context pointer
    ASSERT(groupFile->lpInternal != NULL);
    mod = groupFile->lpInternal;

    // There must not be an existing file handle
    ASSERT(mod->file == INVALID_HANDLE_VALUE);

    // Retrieve group file location
    StringCchPrintfA(buffer, ELEMENT_COUNT(buffer), "%i", groupId);
    path = Io_ConfigGetPath("Locations", "Group_Files", buffer, NULL);
    if (path == NULL) {
        TRACE("Unable to retrieve file location.");
        return ERROR_NOT_ENOUGH_MEMORY;
    }

    // Open group file
    mod->file = CreateFileA(path,
        GENERIC_READ|GENERIC_WRITE,
        FILE_SHARE_READ|FILE_SHARE_WRITE|FILE_SHARE_DELETE,
        NULL, OPEN_EXISTING, 0, NULL);

    if (mod->file != INVALID_HANDLE_VALUE) {
        result = ERROR_SUCCESS;
    } else {
        result = GetLastError();
        TRACE("Unable to open file \"%s\" (error %lu).", path, result);
    }

    Io_Free(path);
    return result;
}
Пример #20
0
/*++

ConnectionOpen

    Opens a server connection.

Arguments:
    context - Opaque context passed to <PoolCreate>.

    data    - Pointer to a pointer that receives the DB_CONTEXT structure.

Return Values:
    If the function succeeds, the return value is nonzero (true).

    If the function fails, the return value is zero (false).

--*/
static BOOL FCALL ConnectionOpen(VOID *context, VOID **data)
{
    DB_CONTEXT          *db;
    DB_CONFIG_SERVER    *server;
    DWORD               error;
    DWORD               i;
    INT                 attempt;
    INT                 attemptMax;
    LONG                serverIndex;
    LONG                serverNextIndex;
    MYSQL               *connection;
    my_bool             optReconnect;
    UINT                optTimeout;

    UNREFERENCED_PARAMETER(context);
    ASSERT(data != NULL);
    TRACE("context=%p data=%p", context, data);

    db = MemAllocate(sizeof(DB_CONTEXT));
    if (db == NULL) {
        LOG_ERROR("Unable to allocate memory for database context.");

        error = ERROR_NOT_ENOUGH_MEMORY;
        goto failed;
    }
    ZeroMemory(db, sizeof(DB_CONTEXT));

    //
    // Have the MySQL client library allocate the handle structure for us. This is
    // in case the MYSQL structure changes in a future version of the client library.
    //
    db->handle = mysql_init(NULL);
    if (db->handle == NULL) {
        LOG_ERROR("Unable to allocate memory for MySQL handle.");

        error = ERROR_NOT_ENOUGH_MEMORY;
        goto failed;
    }

    // If the maximum number of attempts were not specified, try all servers
    if (dbConfigGlobal.connAttempts > 0) {
        attemptMax = dbConfigGlobal.connAttempts;
    } else {
        attemptMax = dbConfigServerCount;
    }

    for (attempt = 0; attempt < attemptMax; attempt++) {
        // Use the most recent server for the connection attempt
        serverIndex = dbIndex;
        server      = &dbConfigServers[serverIndex];

        TRACE("Connecting to server #%d [%s] on attempt %lu/%lu.",
            serverIndex, server->name, attempt+1, attemptMax);

        // Set connection options
        optTimeout = (UINT)dbConfigGlobal.connTimeout;
        if (mysql_options(db->handle, MYSQL_OPT_CONNECT_TIMEOUT, &optTimeout) != 0) {
            TRACE("Failed to set connection timeout option.");
        }

        optReconnect = FALSE;
        if (mysql_options(db->handle, MYSQL_OPT_RECONNECT, &optReconnect) != 0) {
            TRACE("Failed to set reconnection option.");
        }

        if (server->compression) {
            if (mysql_options(db->handle, MYSQL_OPT_COMPRESS, 0) != 0) {
                TRACE("Failed to set compression option.");
            }
        }

        if (server->sslEnable) {
            //
            // This function always returns 0. If the SSL setup is incorrect,
            // the call to mysql_real_connect() will return an error.
            //
            mysql_ssl_set(db->handle, server->sslKeyFile, server->sslCertFile,
                server->sslCAFile, server->sslCAPath, server->sslCiphers);
        }

        // Attempt connection with server
        connection = mysql_real_connect(db->handle,
            server->host, server->user, server->password,
            server->database, server->port, NULL, CLIENT_INTERACTIVE);

        if (connection == NULL) {
            LOG_ERROR("Unable to connect to server [%s]: %s",
                server->name, mysql_error(db->handle));

        } else if (mysql_get_server_version(db->handle) < 50019) {
            LOG_ERROR("Unsupported version of MySQL Server [%s]: running v%s, must be v5.0.19 or newer.",
                server->name, mysql_get_server_info(db->handle));

        } else {
            // Pointer values should be the same as from mysql_init()
            ASSERT(connection == db->handle);

            // Allocate pre-compiled statement structures
            for (i = 0; i < ELEMENT_COUNT(db->stmt); i++) {
                db->stmt[i] = mysql_stmt_init(db->handle);
                if (db->stmt[i] == NULL) {
                    LOG_ERROR("Unable to allocate memory for statement structure.");

                    error = ERROR_NOT_ENOUGH_MEMORY;
                    goto failed;
                }
            }

            // Successfully connected, set the global server index
            InterlockedExchange(&dbIndex, serverIndex);

            // Update context's server index and time stamps
            db->index = serverIndex;
            GetSystemTimeAsFileTime(&db->created.fileTime);
            db->used.value = db->created.value;

            LOG_INFO("Connected to %s [%s], running MySQL Server v%s.",
                mysql_get_host_info(db->handle), server->name,
                mysql_get_server_info(db->handle));

            *data = db;
            return TRUE;
        }

        // Unsuccessful connection, continue to the next server
        serverNextIndex = serverIndex + 1;
        if (serverNextIndex >= (LONG)dbConfigServerCount) {
            serverNextIndex = 0;
        }

        //
        // Compare the current server index before swapping values in the
        // event that another thread has already changed the index.
        //
        InterlockedCompareExchange(&dbIndex, serverNextIndex, serverIndex);
    }

    // Unable to connect to any servers
    error = ERROR_CONNECTION_REFUSED;

failed:
    if (db != NULL) {
        ConnectionClose(NULL, db);
    }
    SetLastError(error);
    return FALSE;
}