1/*
2 * Copyright (c) 2013, 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#include "jni.h"
28#include "net_util.h"
29#include "sun_net_PortConfig.h"
30
31#ifdef __cplusplus
32extern "C" {
33#endif
34
35struct portrange {
36    int lower;
37    int higher;
38};
39
40static int getPortRange(struct portrange *range)
41{
42    OSVERSIONINFO ver;
43    ver.dwOSVersionInfoSize = sizeof(ver);
44    GetVersionEx(&ver);
45
46    /* Check for major version 5 or less = Windows XP/2003 or older */
47    if (ver.dwMajorVersion <= 5) {
48        LONG ret;
49        HKEY hKey;
50        range->lower = 1024;
51        range->higher = 4999;
52
53        /* check registry to see if upper limit was raised */
54        ret = RegOpenKeyEx(HKEY_LOCAL_MACHINE,
55                   "SYSTEM\\CurrentControlSet\\Services\\Tcpip\\Parameters",
56                   0, KEY_READ, (PHKEY)&hKey
57        );
58        if (ret == ERROR_SUCCESS) {
59            DWORD maxuserport;
60            ULONG ulType;
61            DWORD dwLen = sizeof(maxuserport);
62            ret = RegQueryValueEx(hKey, "MaxUserPort",  NULL, &ulType,
63                             (LPBYTE)&maxuserport, &dwLen);
64            RegCloseKey(hKey);
65            if (ret == ERROR_SUCCESS) {
66                range->higher = maxuserport;
67            }
68        }
69    } else {
70        /* There doesn't seem to be an API to access this. "MaxUserPort"
71          * is affected, but is not sufficient to determine.
72         * so we just use the defaults, which are less likely to change
73          */
74        range->lower = 49152;
75        range->higher = 65535;
76    }
77    return 0;
78}
79
80/*
81 * Class:     sun_net_PortConfig
82 * Method:    getLower0
83 * Signature: ()I
84 */
85JNIEXPORT jint JNICALL Java_sun_net_PortConfig_getLower0
86  (JNIEnv *env, jclass clazz)
87{
88    struct portrange range;
89    getPortRange(&range);
90    return range.lower;
91}
92
93/*
94 * Class:     sun_net_PortConfig
95 * Method:    getUpper0
96 * Signature: ()I
97 */
98JNIEXPORT jint JNICALL Java_sun_net_PortConfig_getUpper0
99  (JNIEnv *env, jclass clazz)
100{
101    struct portrange range;
102    getPortRange(&range);
103    return range.higher;
104}
105#ifdef __cplusplus
106}
107#endif
108