1/*
2 * Copyright (c) 2008, 2015, Oracle and/or its affiliates. All rights reserved.
3 * DO NOT ALTER OR REMOVE COPYRIGHT NOTICES OR THIS FILE HEADER.
4 *
5 * This code is free software; you can redistribute it and/or modify it
6 * under the terms of the GNU General Public License version 2 only, as
7 * published by the Free Software Foundation.  Oracle designates this
8 * particular file as subject to the "Classpath" exception as provided
9 * by Oracle in the LICENSE file that accompanied this code.
10 *
11 * This code is distributed in the hope that it will be useful, but WITHOUT
12 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
13 * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
14 * version 2 for more details (a copy is included in the LICENSE file that
15 * accompanied this code).
16 *
17 * You should have received a copy of the GNU General Public License version
18 * 2 along with this work; if not, write to the Free Software Foundation,
19 * Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA.
20 *
21 * Please contact Oracle, 500 Oracle Parkway, Redwood Shores, CA 94065 USA
22 * or visit www.oracle.com if you need additional information or have any
23 * questions.
24 */
25
26#include <windows.h>
27
28#include "jni.h"
29#include "jni_util.h"
30#include "jlong.h"
31#include "nio.h"
32#include "nio_util.h"
33
34#include "sun_nio_ch_Iocp.h"
35
36
37static jfieldID completionStatus_error;
38static jfieldID completionStatus_bytesTransferred;
39static jfieldID completionStatus_completionKey;
40static jfieldID completionStatus_overlapped;
41
42
43JNIEXPORT void JNICALL
44Java_sun_nio_ch_Iocp_initIDs(JNIEnv* env, jclass this)
45{
46    jclass clazz;
47
48    clazz = (*env)->FindClass(env, "sun/nio/ch/Iocp$CompletionStatus");
49    CHECK_NULL(clazz);
50    completionStatus_error = (*env)->GetFieldID(env, clazz, "error", "I");
51    CHECK_NULL(completionStatus_error);
52    completionStatus_bytesTransferred = (*env)->GetFieldID(env, clazz, "bytesTransferred", "I");
53    CHECK_NULL(completionStatus_bytesTransferred);
54    completionStatus_completionKey = (*env)->GetFieldID(env, clazz, "completionKey", "I");
55    CHECK_NULL(completionStatus_completionKey);
56    completionStatus_overlapped = (*env)->GetFieldID(env, clazz, "overlapped", "J");
57    CHECK_NULL(completionStatus_overlapped);
58}
59
60JNIEXPORT jlong JNICALL
61Java_sun_nio_ch_Iocp_createIoCompletionPort(JNIEnv* env, jclass this,
62    jlong handle, jlong existingPort, jint completionKey, jint concurrency)
63{
64    ULONG_PTR ck = completionKey;
65    HANDLE port = CreateIoCompletionPort((HANDLE)jlong_to_ptr(handle),
66                                         (HANDLE)jlong_to_ptr(existingPort),
67                                         ck,
68                                         (DWORD)concurrency);
69    if (port == NULL) {
70        JNU_ThrowIOExceptionWithLastError(env, "CreateIoCompletionPort failed");
71    }
72    return ptr_to_jlong(port);
73}
74
75JNIEXPORT void JNICALL
76Java_sun_nio_ch_Iocp_close0(JNIEnv* env, jclass this,
77    jlong handle)
78{
79    HANDLE h = (HANDLE)jlong_to_ptr(handle);
80    CloseHandle(h);
81}
82
83
84JNIEXPORT void JNICALL
85Java_sun_nio_ch_Iocp_getQueuedCompletionStatus(JNIEnv* env, jclass this,
86    jlong completionPort, jobject obj)
87{
88    DWORD bytesTransferred;
89    ULONG_PTR completionKey;
90    OVERLAPPED *lpOverlapped;
91    BOOL res;
92
93    res = GetQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
94                                  &bytesTransferred,
95                                  &completionKey,
96                                  &lpOverlapped,
97                                  INFINITE);
98    if (res == 0 && lpOverlapped == NULL) {
99        JNU_ThrowIOExceptionWithLastError(env, "GetQueuedCompletionStatus failed");
100    } else {
101        DWORD ioResult = (res == 0) ? GetLastError() : 0;
102        (*env)->SetIntField(env, obj, completionStatus_error, ioResult);
103        (*env)->SetIntField(env, obj, completionStatus_bytesTransferred,
104            (jint)bytesTransferred);
105        (*env)->SetIntField(env, obj, completionStatus_completionKey,
106            (jint)completionKey);
107        (*env)->SetLongField(env, obj, completionStatus_overlapped,
108            ptr_to_jlong(lpOverlapped));
109
110    }
111}
112
113JNIEXPORT void JNICALL
114Java_sun_nio_ch_Iocp_postQueuedCompletionStatus(JNIEnv* env, jclass this,
115    jlong completionPort, jint completionKey)
116{
117    BOOL res;
118
119    res = PostQueuedCompletionStatus((HANDLE)jlong_to_ptr(completionPort),
120                                     (DWORD)0,
121                                     (DWORD)completionKey,
122                                     NULL);
123    if (res == 0) {
124        JNU_ThrowIOExceptionWithLastError(env, "PostQueuedCompletionStatus");
125    }
126}
127
128JNIEXPORT jstring JNICALL
129Java_sun_nio_ch_Iocp_getErrorMessage(JNIEnv* env, jclass this, jint errorCode)
130{
131    WCHAR message[255];
132
133    DWORD len = FormatMessageW(FORMAT_MESSAGE_FROM_SYSTEM,
134                               NULL,
135                               (DWORD)errorCode,
136                               0,
137                               &message[0],
138                               255,
139                               NULL);
140
141
142    if (len == 0) {
143        return NULL;
144    } else {
145        return (*env)->NewString(env, (const jchar *)message, (jsize)wcslen(message));
146    }
147}
148