Exemplo n.º 1
0
    DWORD CALLBACK Thread()
    {
        IMDPROXY_CONNECT_REQ ConnectReq;

        KdPrint(("ImDskSvc: Thread created.%n"));

        if (Overlapped.BufRecv(hPipe, &ConnectReq.request_code,
            sizeof ConnectReq.request_code) !=
            sizeof ConnectReq.request_code)
        {
            KdPrintLastError(("Overlapped.BufRecv() failed"));

            delete this;
            return 0;
        }

        if (ConnectReq.request_code != IMDPROXY_REQ_CONNECT)
        {
            delete this;
            return 0;
        }

        if (Overlapped.BufRecv(hPipe,
            ((PUCHAR)&ConnectReq) +
            sizeof(ConnectReq.request_code),
            sizeof(ConnectReq) -
            sizeof(ConnectReq.request_code)) !=
            sizeof(ConnectReq) -
            sizeof(ConnectReq.request_code))
        {
            KdPrintLastError(("Overlapped.BufRecv() failed"));

            delete this;
            return 0;
        }

        if ((ConnectReq.length == 0) | (ConnectReq.length > 520))
        {
            KdPrint(("ImDskSvc: Bad connection string length received (%1!u!).%n",
                ConnectReq.length));

            delete this;
            return 0;
        }

        WCRTMem<WCHAR> ConnectionString((size_t)ConnectReq.length + 2);
        if (!ConnectionString)
        {
            KdPrintLastError(("malloc() failed"));

            delete this;
            return 0;
        }

        if (Overlapped.BufRecv(hPipe, ConnectionString,
            (DWORD)ConnectReq.length) !=
            ConnectReq.length)
        {
            KdPrintLastError(("Overlapped.BufRecv() failed"));

            
            delete this;
            return 0;
        }

        IMDPROXY_CONNECT_RESP connect_resp = { 0 };

        ConnectionString[ConnectReq.length / sizeof *ConnectionString] = 0;

        // Split server connection string and string that should be sent to server
        // for server side connection to specific image file.

        LPWSTR path_part = wcsstr(ConnectionString, L"://");

        if (path_part != NULL)
        {
            path_part[0] = 0;
            path_part++;
        }

        HANDLE hTarget;
        switch (IMDISK_PROXY_TYPE(ConnectReq.flags))
        {
        case IMDISK_PROXY_TYPE_COMM:
        {
            LPWSTR FileName = wcstok(ConnectionString, L": ");

            KdPrint(("ImDskSvc: Connecting to '%1!ws!'.%n", FileName));

            hTarget = CreateFile(FileName,
                GENERIC_READ | GENERIC_WRITE,
                0,
                NULL,
                OPEN_EXISTING,
                0,
                NULL);

            if (hTarget == INVALID_HANDLE_VALUE)
            {
                connect_resp.error_code = GetLastError();

                KdPrintLastError(("CreateFile() failed"));

                Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

                delete this;
                return 0;
            }

            LPWSTR DCBAndTimeouts = wcstok(NULL, L"");
            if (DCBAndTimeouts != NULL)
            {
                DCB dcb = { 0 };
                COMMTIMEOUTS timeouts = { 0 };

                if (DCBAndTimeouts[0] == L' ')
                    ++DCBAndTimeouts;

                KdPrint(("ImDskSvc: Configuring '%1!ws!'.%n", DCBAndTimeouts));

                GetCommState(hTarget, &dcb);
                GetCommTimeouts(hTarget, &timeouts);
                BuildCommDCBAndTimeouts(DCBAndTimeouts, &dcb, &timeouts);
                SetCommState(hTarget, &dcb);
                SetCommTimeouts(hTarget, &timeouts);
            }

            KdPrint(("ImDskSvc: Connected to '%1!ws!' and configured.%n",
                FileName));

            break;
        }

        case IMDISK_PROXY_TYPE_TCP:
        {
            LPWSTR ServerName = wcstok(ConnectionString, L":");
            LPWSTR PortName = wcstok(NULL, L"");

            if (PortName == NULL)
                PortName = L"9000";

            KdPrint(("ImDskSvc: Connecting to '%1!ws!:%2!ws!'.%n",
                ServerName, PortName));

            hTarget = (HANDLE)ConnectTCP(ServerName, PortName);
            if (hTarget == INVALID_HANDLE_VALUE)
            {
                connect_resp.error_code = GetLastError();

                KdPrintLastError(("ConnectTCP() failed"));
                

                Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

                delete this;
                return 0;
            }

            bool b = true;
            setsockopt((SOCKET)hTarget, IPPROTO_TCP, TCP_NODELAY, (LPCSTR)&b,
                sizeof b);

            KdPrint(("ImDskSvc: Connected to '%1!ws!:%2!ws!' and configured.%n",
                ServerName, PortName));

            break;
        }

        default:
            KdPrint(("ImDskSvc: Unsupported connection type (%1!#x!).%n",
                IMDISK_PROXY_TYPE(ConnectReq.flags)));

            connect_resp.error_code = (ULONGLONG)-1;
            Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

            
            delete this;
            return 0;
        }

        // Connect to requested server side image path

        if (path_part != NULL)
        {
            size_t path_size = wcslen(path_part) << 1;

            size_t req_size = sizeof(IMDPROXY_CONNECT_REQ) +
                path_size;

            WCRTMem<IMDPROXY_CONNECT_REQ> open_request(req_size);

            if (!open_request)
            {
                KdPrintLastError(("malloc() failed"));

                connect_resp.error_code = (ULONGLONG)-1;
                Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

                delete this;
                return 0;
            }

            ZeroMemory(open_request, req_size);

            open_request->request_code = IMDPROXY_REQ_CONNECT;
            open_request->length = path_size;

            memcpy(open_request + 1, path_part, path_size);

            if (!Overlapped.BufSend(hTarget, open_request, (DWORD)req_size))
            {
                KdPrintLastError(("Failed to send connect request to server"));

                connect_resp.error_code = (ULONGLONG)-1;
                Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

                delete this;
                return 0;
            }

            open_request.Free();

            if (Overlapped.BufRecv(hTarget, &connect_resp, sizeof connect_resp) !=
                sizeof connect_resp)
            {
                connect_resp.object_ptr = NULL;
                if (connect_resp.error_code == 0)
                {
                    connect_resp.error_code = (ULONGLONG)-1;
                }

                Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);
                
                delete this;
                return 0;
            }
        }
        
        ConnectionString.Free();

        HANDLE hDriver = CreateFile(IMDISK_CTL_DOSDEV_NAME,
            GENERIC_READ | GENERIC_WRITE,
            FILE_SHARE_READ | FILE_SHARE_WRITE,
            NULL,
            OPEN_EXISTING,
            0,
            NULL);

        if (hDriver == INVALID_HANDLE_VALUE)
        {
            connect_resp.error_code = GetLastError();

            KdPrintLastError(("Opening ImDiskCtl device failed"));
            CloseHandle(hTarget);

            Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

            delete this;
            return 0;
        }

        DWORD dw;
        if (!DeviceIoControl(hDriver,
            IOCTL_IMDISK_REFERENCE_HANDLE,
            &hTarget,
#pragma warning(suppress: 28132)
            sizeof hTarget,
            &connect_resp.object_ptr,
            sizeof connect_resp.object_ptr,
            &dw,
            NULL))
        {
            connect_resp.error_code = GetLastError();

            KdPrintLastError(("IOCTL_IMDISK_REFERENCE_HANDLE failed"));
            CloseHandle(hDriver);
            CloseHandle(hTarget);

            Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

            delete this;
            return 0;
        }

        CloseHandle(hDriver);

        Overlapped.BufSend(hPipe, &connect_resp, sizeof connect_resp);

        // This will fail when driver closes the pipe, but that just indicates that
        // we should shut down this connection.
        Overlapped.BufRecv(hPipe, &dw, sizeof dw);

        KdPrint(("ImDskSvc: Cleaning up.%n"));

        CloseHandle(hTarget);

        delete this;
        return 1;
    }
Exemplo n.º 2
0
int
safe_read(SOCKET fd, void *pdata, safeio_size_t size)
{
  return Overlapped.BufRecv((HANDLE) fd, pdata, size) == (DWORD)size;
}