CreateFile () возвращает INVALID_HANDLE_VALUE, но GetLastError () - ERROR_SUCCESS - PullRequest
8 голосов
/ 05 октября 2011

Я открываю последовательный порт, используя CreateFile () .У меня есть тестовый сценарий (слишком сложный для перераспределения), который постоянно заставляет CreateFile() возвращать INVALID_HANDLE_VALUE и GetLastError() возвращать ERROR_SUCCESS.Судя по всему, эта ошибка возникает, только если один поток открывает порт в то же самое время, когда другой порт закрывает его.Поток, открывающий порт, проходит через эту проблему.

Я не знаю, имеет ли это значение, но позже в коде я связываю порт с CompletionPort, используя CreateIoCompletionPort .

Вот мой код:

HANDLE port = CreateFile(L"\\\\.\\COM1",
                         GENERIC_READ | GENERIC_WRITE,
                         0,                    // must be opened with exclusive-access
                         0,                    // default security attributes
                         OPEN_EXISTING,        // must use OPEN_EXISTING
                         FILE_FLAG_OVERLAPPED, // overlapped I/O
                         0);                   // hTemplate must be NULL for comm devices
if (port == INVALID_HANDLE_VALUE)
{
    DWORD errorCode = GetLastError();
    cerr << L"CreateFile() failed with error: " << errorCode << endl;
}

Я почти уверен, что такого не должно быть.Я делаю что-то не так?Как заставить API возвращать правильный результат?


БОЛЬШЕ ДЕТАЛЕЙ : Этот код взят из разработанной мной библиотеки последовательного порта: JPeripheral

Вот фактический (неанизированный) исходный код:

JLong SerialChannel::nativeOpen(String name)
{
    cerr << "nativeOpen(" << name << ")" << endl;
    wstring nameWstring = name;
    HANDLE port = CreateFile((L"\\\\.\\" + nameWstring).c_str(),
        GENERIC_READ | GENERIC_WRITE,
        0,                                          // must be opened with exclusive-access
        0,                                          // default security attributes
        OPEN_EXISTING,                  // must use OPEN_EXISTING
        FILE_FLAG_OVERLAPPED,       // overlapped I/O
        0);                                         // hTemplate must be NULL for comm devices
    cerr << "nativeOpen.afterCreateFile(" << name << ")" << endl;
    cerr << "port: " << port << ", errorCode: " << GetLastError() << endl;
    if (port == INVALID_HANDLE_VALUE)
    {
        DWORD errorCode = GetLastError();

        switch (errorCode)
        {
            case ERROR_FILE_NOT_FOUND:
                throw PeripheralNotFoundException(jace::java_new<PeripheralNotFoundException>(name, Throwable()));
            case ERROR_ACCESS_DENIED:
            case ERROR_SHARING_VIOLATION:
                throw PeripheralInUseException(jace::java_new<PeripheralInUseException>(name, Throwable()));
            default:
            {
                throw IOException(jace::java_new<IOException>(L"CreateFile() failed with error: " +
                    getErrorMessage(GetLastError())));
            }
        }
    }

    // Associate the file handle with the existing completion port
    HANDLE completionPort = CreateIoCompletionPort(port, ::jperipheral::worker->completionPort, Task::COMPLETION, 0);
    if (completionPort==0)
    {
        throw AssertionError(jace::java_new<AssertionError>(L"CreateIoCompletionPort() failed with error: " +
            getErrorMessage(GetLastError())));
    }
    cerr << "nativeOpen.afterCompletionPort(" << name << ")" << endl;

    // Bind the native serial port to Java serial port
    SerialPortContext* result = new SerialPortContext(port);
    cerr << "nativeOpen.afterContext(" << name << ")" << endl;
    return reinterpret_cast<intptr_t>(result);
}

Вот фактический вывод, который я получаю:

nativeOpen(COM1)
nativeOpen.afterCreateFile(COM1)
port: 00000374, errorCode: 0
nativeOpen.afterCompletionPort(COM1)
nativeOpen.afterContext(COM1)
[...]
nativeOpen(COM1)
nativeOpen.afterCreateFile(COM1)
port: FFFFFFFF, errorCode: 0
java.io.IOException: CreateFile() failed with error: The operation completed successfully.

1 Ответ

9 голосов
/ 05 октября 2011
 HANDLE port = CreateFile(...);
 cerr << "nativeOpen.afterCreateFile(" << name << ")" << endl;
 cerr << "port: " << port << ", errorCode: " << GetLastError() << endl;
 if (port == INVALID_HANDLE_VALUE)
 {
    DWORD errorCode = GetLastError();

Выходные данные для cerr вызывают вызовы winapi под капотом. Который будет сбрасывать значение ошибки потока, возвращенное GetLastError (). Исправлено:

 HANDLE port = CreateFile(...);
 int err = GetLastError();
 // etc, use err instead...
...