~ubuntu-branches/ubuntu/quantal/ruby1.9.1/quantal

« back to all changes in this revision

Viewing changes to win32/win32.c

  • Committer: Bazaar Package Importer
  • Author(s): Lucas Nussbaum
  • Date: 2011-09-24 19:16:17 UTC
  • mfrom: (1.1.8 upstream) (13.1.7 experimental)
  • Revision ID: james.westby@ubuntu.com-20110924191617-o1qz4rcmqjot8zuy
Tags: 1.9.3~rc1-1
* New upstream release: 1.9.3 RC1.
  + Includes load.c fixes. Closes: #639959.
* Upload to unstable.

Show diffs side-by-side

added added

removed removed

Lines of Context:
63
63
 
64
64
#define TO_SOCKET(x)    _get_osfhandle(x)
65
65
 
66
 
static struct ChildRecord *CreateChild(const char *, const char *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE);
 
66
static struct ChildRecord *CreateChild(const WCHAR *, const WCHAR *, SECURITY_ATTRIBUTES *, HANDLE, HANDLE, HANDLE);
67
67
static int has_redirection(const char *);
68
68
int rb_w32_wait_events(HANDLE *events, int num, DWORD timeout);
69
69
static int rb_w32_open_osfhandle(intptr_t osfhandle, int flags);
252
252
}
253
253
#endif
254
254
 
255
 
static DWORD
 
255
DWORD
256
256
rb_w32_osver(void)
257
257
{
258
258
    return osver.dwMajorVersion;
450
450
    }
451
451
}
452
452
 
 
453
static FARPROC
 
454
get_proc_address(const char *module, const char *func, HANDLE *mh)
 
455
{
 
456
    HANDLE h;
 
457
    FARPROC ptr;
 
458
 
 
459
    if (mh)
 
460
        h = LoadLibrary(module);
 
461
    else
 
462
        h = GetModuleHandle(module);
 
463
    if (!h)
 
464
        return NULL;
 
465
 
 
466
    ptr = GetProcAddress(h, func);
 
467
    if (mh) {
 
468
        if (ptr)
 
469
            *mh = h;
 
470
        else
 
471
            FreeLibrary(h);
 
472
    }
 
473
    return ptr;
 
474
}
 
475
 
453
476
static UINT
454
477
get_system_directory(WCHAR *path, UINT len)
455
478
{
456
 
    HANDLE hKernel = GetModuleHandle("kernel32.dll");
457
 
 
458
 
    if (hKernel) {
459
 
        typedef UINT WINAPI wgetdir_func(WCHAR*, UINT);
460
 
        FARPROC ptr = GetProcAddress(hKernel, "GetSystemWindowsDirectoryW");
461
 
        if (ptr) {
462
 
            return (*(wgetdir_func *)ptr)(path, len);
463
 
        }
464
 
    }
 
479
    typedef UINT WINAPI wgetdir_func(WCHAR*, UINT);
 
480
    FARPROC ptr =
 
481
        get_proc_address("kernel32", "GetSystemWindowsDirectoryW", NULL);
 
482
    if (ptr)
 
483
        return (*(wgetdir_func *)ptr)(path, len);
465
484
    return GetWindowsDirectoryW(path, len);
466
485
}
467
486
 
569
588
init_func(void)
570
589
{
571
590
    if (!cancel_io)
572
 
        cancel_io = (cancel_io_t)GetProcAddress(GetModuleHandle("kernel32"),
573
 
                                                "CancelIo");
 
591
        cancel_io = (cancel_io_t)get_proc_address("kernel32", "CancelIo", NULL);
574
592
}
575
593
 
576
594
static void init_stdhandle(void);
836
854
    do {
837
855
        if (!(c = *cmd++)) return 0;
838
856
    } while (isspace(c));
 
857
    if (c == '@')
 
858
        return 1;
839
859
    while (isalpha(c)) {
840
860
        *b++ = tolower(c);
841
861
        if (b == cmdname + sizeof(cmdname)) return 0;
948
968
# define MAXPATHLEN 512
949
969
#endif
950
970
 
951
 
#define STRNDUPA(ptr, src, len) \
952
 
    (((char *)memcpy(((ptr) = ALLOCA_N(char, (len) + 1)), (src), (len)))[len] = 0)
 
971
#define STRNDUPV(ptr, v, src, len)                                      \
 
972
    (((char *)memcpy(((ptr) = ALLOCV((v), (len) + 1)), (src), (len)))[len] = 0)
953
973
 
954
974
static int
955
975
check_spawn_mode(int mode)
987
1007
}
988
1008
 
989
1009
static struct ChildRecord *
990
 
CreateChild(const char *cmd, const char *prog, SECURITY_ATTRIBUTES *psa,
 
1010
CreateChild(const WCHAR *cmd, const WCHAR *prog, SECURITY_ATTRIBUTES *psa,
991
1011
            HANDLE hInput, HANDLE hOutput, HANDLE hError)
992
1012
{
993
1013
    BOOL fRet;
994
1014
    DWORD  dwCreationFlags;
995
 
    STARTUPINFO aStartupInfo;
 
1015
    STARTUPINFOW aStartupInfo;
996
1016
    PROCESS_INFORMATION aProcessInformation;
997
1017
    SECURITY_ATTRIBUTES sa;
998
1018
    struct ChildRecord *child;
1015
1035
        psa = &sa;
1016
1036
    }
1017
1037
 
1018
 
    memset(&aStartupInfo, 0, sizeof (STARTUPINFO));
1019
 
    memset(&aProcessInformation, 0, sizeof (PROCESS_INFORMATION));
1020
 
    aStartupInfo.cb = sizeof (STARTUPINFO);
 
1038
    memset(&aStartupInfo, 0, sizeof(aStartupInfo));
 
1039
    memset(&aProcessInformation, 0, sizeof(aProcessInformation));
 
1040
    aStartupInfo.cb = sizeof(aStartupInfo);
1021
1041
    aStartupInfo.dwFlags = STARTF_USESTDHANDLES;
1022
1042
    if (hInput) {
1023
1043
        aStartupInfo.hStdInput  = hInput;
1047
1067
    }
1048
1068
 
1049
1069
    RUBY_CRITICAL({
1050
 
        fRet = CreateProcess(prog, (char *)cmd, psa, psa,
1051
 
                             psa->bInheritHandle, dwCreationFlags, NULL, NULL,
1052
 
                             &aStartupInfo, &aProcessInformation);
 
1070
        fRet = CreateProcessW(prog, (WCHAR *)cmd, psa, psa,
 
1071
                              psa->bInheritHandle, dwCreationFlags, NULL, NULL,
 
1072
                              &aStartupInfo, &aProcessInformation);
1053
1073
        errno = map_errno(GetLastError());
1054
1074
    });
1055
1075
 
1083
1103
    return 0;
1084
1104
}
1085
1105
 
 
1106
static UINT filecp(void);
 
1107
static WCHAR *mbstr_to_wstr(UINT, const char *, int, long *);
 
1108
static char *wstr_to_mbstr(UINT, const WCHAR *, int, long *);
 
1109
#define acp_to_wstr(str, plen) mbstr_to_wstr(CP_ACP, str, -1, plen)
 
1110
#define wstr_to_acp(str, plen) wstr_to_mbstr(CP_ACP, str, -1, plen)
 
1111
#define filecp_to_wstr(str, plen) mbstr_to_wstr(filecp(), str, -1, plen)
 
1112
#define wstr_to_filecp(str, plen) wstr_to_mbstr(filecp(), str, -1, plen)
 
1113
#define utf8_to_wstr(str, plen) mbstr_to_wstr(CP_UTF8, str, -1, plen)
 
1114
#define wstr_to_utf8(str, plen) wstr_to_mbstr(CP_UTF8, str, -1, plen)
 
1115
 
1086
1116
rb_pid_t
1087
1117
rb_w32_spawn(int mode, const char *cmd, const char *prog)
1088
1118
{
1089
1119
    char fbuf[MAXPATHLEN];
1090
1120
    char *p = NULL;
1091
1121
    const char *shell = NULL;
 
1122
    WCHAR *wcmd, *wshell;
 
1123
    rb_pid_t ret;
 
1124
    VALUE v = 0;
 
1125
    VALUE v2 = 0;
1092
1126
 
1093
1127
    if (check_spawn_mode(mode)) return -1;
1094
1128
 
1106
1140
        int nt;
1107
1141
        while (ISSPACE(*cmd)) cmd++;
1108
1142
        if ((shell = getenv("RUBYSHELL")) && (redir = has_redirection(cmd))) {
1109
 
            char *tmp = ALLOCA_N(char, strlen(shell) + strlen(cmd) + sizeof(" -c ") + 2);
 
1143
            char *tmp = ALLOCV(v, strlen(shell) + strlen(cmd) + sizeof(" -c ") + 2);
1110
1144
            sprintf(tmp, "%s -c \"%s\"", shell, cmd);
1111
1145
            cmd = tmp;
1112
1146
        }
1114
1148
                 (nt = !is_command_com(shell),
1115
1149
                  (redir < 0 ? has_redirection(cmd) : redir) ||
1116
1150
                  is_internal_cmd(cmd, nt))) {
1117
 
            char *tmp = ALLOCA_N(char, strlen(shell) + strlen(cmd) + sizeof(" /c ")
1118
 
                                 + (nt ? 2 : 0));
 
1151
            char *tmp = ALLOCV(v, strlen(shell) + strlen(cmd) + sizeof(" /c ") + (nt ? 2 : 0));
1119
1152
            sprintf(tmp, nt ? "%s /c \"%s\"" : "%s /c %s", shell, cmd);
1120
1153
            cmd = tmp;
1121
1154
        }
1129
1162
                }
1130
1163
                if ((unsigned char)*prog == quote) {
1131
1164
                    len = prog++ - cmd - 1;
1132
 
                    STRNDUPA(p, cmd + 1, len);
 
1165
                    STRNDUPV(p, v2, cmd + 1, len);
1133
1166
                    shell = p;
1134
1167
                    break;
1135
1168
                }
1136
1169
                if (quote) continue;
1137
1170
                if (ISSPACE(*prog) || strchr("<>|*?\"", *prog)) {
1138
1171
                    len = prog - cmd;
1139
 
                    STRNDUPA(p, cmd, len);
 
1172
                    STRNDUPV(p, v2, cmd, len);
1140
1173
                    shell = p;
1141
1174
                    break;
1142
1175
                }
1152
1185
                    p = fbuf;
1153
1186
                }
1154
1187
                else if (shell != p && strchr(shell, '/')) {
1155
 
                    STRNDUPA(p, shell, len);
 
1188
                    STRNDUPV(p, v2, shell, len);
1156
1189
                    shell = p;
1157
1190
                }
1158
1191
                if (p) translate_char(p, '/', '\\');
1159
1192
                if (is_batch(shell)) {
1160
1193
                    int alen = strlen(prog);
1161
 
                    cmd = p = ALLOCA_N(char, len + alen + (quote ? 2 : 0) + 1);
 
1194
                    cmd = p = ALLOCV(v, len + alen + (quote ? 2 : 0) + 1);
1162
1195
                    if (quote) *p++ = '"';
1163
1196
                    memcpy(p, shell, len);
1164
1197
                    p += len;
1170
1203
        }
1171
1204
    }
1172
1205
 
1173
 
    return child_result(CreateChild(cmd, shell, NULL, NULL, NULL, NULL), mode);
 
1206
    /* assume ACP */
 
1207
    wcmd = cmd ? acp_to_wstr(cmd, NULL) : NULL;
 
1208
    if (v) ALLOCV_END(v);
 
1209
    wshell = shell ? acp_to_wstr(shell, NULL) : NULL;
 
1210
    if (v2) ALLOCV_END(v2);
 
1211
 
 
1212
    ret = child_result(CreateChild(wcmd, wshell, NULL, NULL, NULL, NULL), mode);
 
1213
    free(wshell);
 
1214
    free(wcmd);
 
1215
    return ret;
1174
1216
}
1175
1217
 
1176
1218
rb_pid_t
1181
1223
    BOOL ntcmd = FALSE, tmpnt;
1182
1224
    const char *shell;
1183
1225
    char *cmd, fbuf[MAXPATHLEN];
 
1226
    WCHAR *wcmd, *wprog;
 
1227
    rb_pid_t ret;
 
1228
    VALUE v = 0;
1184
1229
 
1185
1230
    if (check_spawn_mode(mode)) return -1;
1186
1231
 
1201
1246
        if (len < sizeof(fbuf))
1202
1247
            strlcpy(cmd = fbuf, prog, sizeof(fbuf));
1203
1248
        else
1204
 
            STRNDUPA(cmd, prog, len);
 
1249
            STRNDUPV(cmd, v, prog, len);
1205
1250
        translate_char(cmd, '/', '\\');
1206
1251
        prog = cmd;
1207
1252
    }
1213
1258
        if (c_switch) len += 3;
1214
1259
        else ++argv;
1215
1260
        if (argv[0]) len += join_argv(NULL, argv, ntcmd);
1216
 
        cmd = ALLOCA_N(char, len);
 
1261
        cmd = ALLOCV(v, len);
1217
1262
        join_argv(cmd, progs, ntcmd);
1218
1263
        if (c_switch) strlcat(cmd, " /c", len);
1219
1264
        if (argv[0]) join_argv(cmd + strlcat(cmd, " ", len), argv, ntcmd);
1221
1266
    }
1222
1267
    else {
1223
1268
        len = join_argv(NULL, argv, FALSE);
1224
 
        cmd = ALLOCA_N(char, len);
 
1269
        cmd = ALLOCV(v, len);
1225
1270
        join_argv(cmd, argv, FALSE);
1226
1271
    }
1227
1272
 
1228
 
    return child_result(CreateChild(cmd, prog, NULL, NULL, NULL, NULL), mode);
 
1273
    /* assume ACP */
 
1274
    wcmd = cmd ? acp_to_wstr(cmd, NULL) : NULL;
 
1275
    if (v) ALLOCV_END(v);
 
1276
    wprog = prog ? acp_to_wstr(prog, NULL) : NULL;
 
1277
 
 
1278
    ret = child_result(CreateChild(wcmd, wprog, NULL, NULL, NULL, NULL), mode);
 
1279
    free(wprog);
 
1280
    free(wcmd);
 
1281
    return ret;
1229
1282
}
1230
1283
 
1231
1284
typedef struct _NtCmdLineElement {
1290
1343
    return tail;
1291
1344
}
1292
1345
 
1293
 
// 
 
1346
//
1294
1347
// Check a command string to determine if it has I/O redirection
1295
1348
// characters that require it to be executed by a command interpreter
1296
1349
//
1350
1403
    return ptr;
1351
1404
}
1352
1405
 
1353
 
int 
 
1406
int
1354
1407
rb_w32_cmdvector(const char *cmd, char ***vec)
1355
1408
{
1356
1409
    int globbing, len;
1378
1431
    //
1379
1432
    // Ok, parse the command line, building a list of CmdLineElements.
1380
1433
    // When we've finished, and it's an input command (meaning that it's
1381
 
    // the processes argv), we'll do globing and then build the argument 
 
1434
    // the processes argv), we'll do globing and then build the argument
1382
1435
    // vector.
1383
 
    // The outer loop does one interation for each element seen. 
 
1436
    // The outer loop does one interation for each element seen.
1384
1437
    // The inner loop does one interation for each character in the element.
1385
1438
    //
1386
1439
 
1417
1470
              case '?':
1418
1471
              case '[':
1419
1472
              case '{':
1420
 
                // 
 
1473
                //
1421
1474
                // record the fact that this element has a wildcard character
1422
1475
                // N.B. Don't glob if inside a single quoted string
1423
1476
                //
1431
1484
              case '\"':
1432
1485
                //
1433
1486
                // if we're already in a string, see if this is the
1434
 
                // terminating close-quote. If it is, we're finished with 
 
1487
                // terminating close-quote. If it is, we're finished with
1435
1488
                // the string, but not neccessarily with the element.
1436
1489
                // If we're not already in a string, start one.
1437
1490
                //
1467
1520
        if (done) --len;
1468
1521
 
1469
1522
        //
1470
 
        // if it's an input vector element and it's enclosed by quotes, 
 
1523
        // if it's an input vector element and it's enclosed by quotes,
1471
1524
        // we can remove them.
1472
1525
        //
1473
1526
 
1529
1582
    }
1530
1583
 
1531
1584
    //
1532
 
    // Almost done! 
 
1585
    // Almost done!
1533
1586
    // Count up the elements, then allocate space for a vector of pointers
1534
1587
    // (argv) and a string table for the elements.
1535
 
    // 
 
1588
    //
1536
1589
 
1537
1590
    for (elements = 0, strsz = 0, curr = cmdhead; curr; curr = curr->next) {
1538
1591
        elements++;
1552
1605
        for (vptr = *vec; *vptr; ++vptr);
1553
1606
        return vptr - *vec;
1554
1607
    }
1555
 
    
 
1608
 
1556
1609
    //
1557
1610
    // make vptr point to the start of the buffer
1558
1611
    // and ptr point to the area we'll consider the string table.
1593
1646
//
1594
1647
// The idea here is to read all the directory names into a string table
1595
1648
// (separated by nulls) and when one of the other dir functions is called
1596
 
// return the pointer to the current file name. 
 
1649
// return the pointer to the current file name.
1597
1650
//
1598
1651
 
1599
1652
#define GetBit(bits, i) ((bits)[(i) / CHAR_BIT] &  (1 << (i) % CHAR_BIT))
1611
1664
    WCHAR *scanname;
1612
1665
    WCHAR *p;
1613
1666
    int len;
 
1667
    VALUE v;
1614
1668
 
1615
1669
    //
1616
1670
    // Create the search pattern
1617
1671
    //
1618
1672
    len = lstrlenW(filename);
1619
 
    scanname = ALLOCA_N(WCHAR, len + sizeof(wildcard) / sizeof(WCHAR));
 
1673
    scanname = ALLOCV_N(WCHAR, v, len + sizeof(wildcard) / sizeof(WCHAR));
1620
1674
    lstrcpyW(scanname, filename);
1621
1675
    p = CharPrevW(scanname, scanname + len);
1622
1676
    if (*p == L'/' || *p == L'\\' || *p == L':')
1628
1682
    // do the FindFirstFile call
1629
1683
    //
1630
1684
    fh = FindFirstFileW(scanname, fd);
 
1685
    ALLOCV_END(v);
1631
1686
    if (fh == INVALID_HANDLE_VALUE) {
1632
1687
        errno = map_errno(GetLastError());
1633
1688
    }
1635
1690
}
1636
1691
 
1637
1692
static DIR *
1638
 
opendir_internal(HANDLE fh, WIN32_FIND_DATAW *fd)
 
1693
opendir_internal(WCHAR *wpath, const char *filename)
1639
1694
{
 
1695
    struct stati64 sbuf;
 
1696
    WIN32_FIND_DATAW fd;
 
1697
    HANDLE fh;
1640
1698
    DIR *p;
1641
1699
    long len;
1642
1700
    long idx;
1643
1701
    WCHAR *tmpW;
1644
1702
    char *tmp;
1645
1703
 
 
1704
    //
 
1705
    // check to see if we've got a directory
 
1706
    //
 
1707
    if (wstati64(wpath, &sbuf) < 0) {
 
1708
        return NULL;
 
1709
    }
 
1710
    if (!(sbuf.st_mode & S_IFDIR) &&
 
1711
        (!ISALPHA(filename[0]) || filename[1] != ':' || filename[2] != '\0' ||
 
1712
         ((1 << ((filename[0] & 0x5f) - 'A')) & GetLogicalDrives()) == 0)) {
 
1713
        errno = ENOTDIR;
 
1714
        return NULL;
 
1715
    }
 
1716
    fh = open_dir_handle(wpath, &fd);
1646
1717
    if (fh == INVALID_HANDLE_VALUE) {
1647
1718
        return NULL;
1648
1719
    }
1663
1734
    // of the previous string found.
1664
1735
    //
1665
1736
    do {
1666
 
        len = lstrlenW(fd->cFileName) + 1;
 
1737
        len = lstrlenW(fd.cFileName) + 1;
1667
1738
 
1668
1739
        //
1669
1740
        // bump the string table size by enough for the
1670
 
        // new name and it's null terminator 
 
1741
        // new name and it's null terminator
1671
1742
        //
1672
1743
        tmpW = realloc(p->start, (idx + len) * sizeof(WCHAR));
1673
1744
        if (!tmpW) {
1679
1750
        }
1680
1751
 
1681
1752
        p->start = tmpW;
1682
 
        memcpy(&p->start[idx], fd->cFileName, len * sizeof(WCHAR));
 
1753
        memcpy(&p->start[idx], fd.cFileName, len * sizeof(WCHAR));
1683
1754
 
1684
1755
        if (p->nfiles % DIRENT_PER_CHAR == 0) {
1685
1756
            tmp = realloc(p->bits, p->nfiles / DIRENT_PER_CHAR + 1);
1688
1759
            p->bits = tmp;
1689
1760
            p->bits[p->nfiles / DIRENT_PER_CHAR] = 0;
1690
1761
        }
1691
 
        if (fd->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
 
1762
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
1692
1763
            SetBit(p->bits, BitOfIsDir(p->nfiles));
1693
 
        if (fd->dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
 
1764
        if (fd.dwFileAttributes & FILE_ATTRIBUTE_REPARSE_POINT)
1694
1765
            SetBit(p->bits, BitOfIsRep(p->nfiles));
1695
1766
 
1696
1767
        p->nfiles++;
1697
1768
        idx += len;
1698
 
    } while (FindNextFileW(fh, fd));
 
1769
    } while (FindNextFileW(fh, &fd));
1699
1770
    FindClose(fh);
1700
1771
    p->size = idx;
1701
1772
    p->curr = p->start;
1702
1773
    return p;
1703
1774
}
1704
1775
 
1705
 
static char *
1706
 
wstr_to_filecp(const WCHAR *wstr, long *plen)
1707
 
{
1708
 
    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1709
 
    char *ptr;
1710
 
    int len = WideCharToMultiByte(cp, 0, wstr, -1, NULL, 0, NULL, NULL) - 1;
1711
 
    if (!(ptr = malloc(len + 1))) return 0;
1712
 
    WideCharToMultiByte(cp, 0, wstr, -1, ptr, len + 1, NULL, NULL);
1713
 
    if (plen) *plen = len;
1714
 
    return ptr;
1715
 
}
1716
 
 
1717
 
static WCHAR *
1718
 
filecp_to_wstr(const char *str, long *plen)
1719
 
{
1720
 
    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
1721
 
    WCHAR *ptr;
1722
 
    int len = MultiByteToWideChar(cp, 0, str, -1, NULL, 0) - 1;
1723
 
    if (!(ptr = malloc(sizeof(WCHAR) * (len + 1)))) return 0;
1724
 
    MultiByteToWideChar(cp, 0, str, -1, ptr, len + 1);
1725
 
    if (plen) *plen = len;
1726
 
    return ptr;
1727
 
}
1728
 
 
1729
 
static char *
1730
 
wstr_to_utf8(const WCHAR *wstr, long *plen)
1731
 
{
1732
 
    char *ptr;
1733
 
    int len = WideCharToMultiByte(CP_UTF8, 0, wstr, -1, NULL, 0, NULL, NULL) - 1;
1734
 
    if (!(ptr = malloc(len + 1))) return 0;
1735
 
    WideCharToMultiByte(CP_UTF8, 0, wstr, -1, ptr, len + 1, NULL, NULL);
1736
 
    if (plen) *plen = len;
1737
 
    return ptr;
1738
 
}
1739
 
 
1740
 
static WCHAR *
1741
 
utf8_to_wstr(const char *str, long *plen)
1742
 
{
1743
 
    WCHAR *ptr;
1744
 
    int len = MultiByteToWideChar(CP_UTF8, 0, str, -1, NULL, 0) - 1;
1745
 
    if (!(ptr = malloc(sizeof(WCHAR) * (len + 1)))) return 0;
1746
 
    MultiByteToWideChar(CP_UTF8, 0, str, -1, ptr, len + 1);
 
1776
static inline UINT
 
1777
filecp(void)
 
1778
{
 
1779
    UINT cp = AreFileApisANSI() ? CP_ACP : CP_OEMCP;
 
1780
    return cp;
 
1781
}
 
1782
 
 
1783
static char *
 
1784
wstr_to_mbstr(UINT cp, const WCHAR *wstr, int clen, long *plen)
 
1785
{
 
1786
    char *ptr;
 
1787
    int len = WideCharToMultiByte(cp, 0, wstr, clen, NULL, 0, NULL, NULL) - 1;
 
1788
    if (!(ptr = malloc(len + 1))) return 0;
 
1789
    WideCharToMultiByte(cp, 0, wstr, clen, ptr, len + 1, NULL, NULL);
 
1790
    if (plen) *plen = len;
 
1791
    return ptr;
 
1792
}
 
1793
 
 
1794
static WCHAR *
 
1795
mbstr_to_wstr(UINT cp, const char *str, int clen, long *plen)
 
1796
{
 
1797
    WCHAR *ptr;
 
1798
    int len = MultiByteToWideChar(cp, 0, str, clen, NULL, 0) - 1;
 
1799
    if (!(ptr = malloc(sizeof(WCHAR) * (len + 1)))) return 0;
 
1800
    MultiByteToWideChar(cp, 0, str, clen, ptr, len + 1);
1747
1801
    if (plen) *plen = len;
1748
1802
    return ptr;
1749
1803
}
1751
1805
DIR *
1752
1806
rb_w32_opendir(const char *filename)
1753
1807
{
1754
 
    struct stati64 sbuf;
1755
 
    WIN32_FIND_DATAW fd;
1756
 
    HANDLE fh;
1757
 
    WCHAR *wpath;
1758
 
 
1759
 
    if (!(wpath = filecp_to_wstr(filename, NULL)))
1760
 
        return NULL;
1761
 
 
1762
 
    //
1763
 
    // check to see if we've got a directory
1764
 
    //
1765
 
    if (wstati64(wpath, &sbuf) < 0) {
1766
 
        free(wpath);
1767
 
        return NULL;
1768
 
    }
1769
 
    if (!(sbuf.st_mode & S_IFDIR) &&
1770
 
        (!ISALPHA(filename[0]) || filename[1] != ':' || filename[2] != '\0' ||
1771
 
         ((1 << ((filename[0] & 0x5f) - 'A')) & GetLogicalDrives()) == 0)) {
1772
 
        free(wpath);
1773
 
        errno = ENOTDIR;
1774
 
        return NULL;
1775
 
    }
1776
 
 
1777
 
    fh = open_dir_handle(wpath, &fd);
1778
 
    free(wpath);
1779
 
    return opendir_internal(fh, &fd);
 
1808
    DIR *ret;
 
1809
    WCHAR *wpath = filecp_to_wstr(filename, NULL);
 
1810
    if (!wpath)
 
1811
        return NULL;
 
1812
    ret = opendir_internal(wpath, filename);
 
1813
    free(wpath);
 
1814
    return ret;
 
1815
}
 
1816
 
 
1817
DIR *
 
1818
rb_w32_uopendir(const char *filename)
 
1819
{
 
1820
    DIR *ret;
 
1821
    WCHAR *wpath = utf8_to_wstr(filename, NULL);
 
1822
    if (!wpath)
 
1823
        return NULL;
 
1824
    ret = opendir_internal(wpath, filename);
 
1825
    free(wpath);
 
1826
    return ret;
1780
1827
}
1781
1828
 
1782
1829
//
1812
1859
{
1813
1860
    static rb_encoding *utf16 = (rb_encoding *)-1;
1814
1861
    VALUE src;
1815
 
    VALUE opthash;
1816
 
    int ecflags;
1817
 
    VALUE ecopts;
1818
1862
 
1819
1863
    if (utf16 == (rb_encoding *)-1) {
1820
1864
        utf16 = rb_enc_find("UTF-16LE");
1826
1870
        return Qnil;
1827
1871
 
1828
1872
    src = rb_enc_str_new((char *)wstr, lstrlenW(wstr) * sizeof(WCHAR), utf16);
1829
 
    opthash = rb_hash_new();
1830
 
    rb_hash_aset(opthash, ID2SYM(rb_intern("undef")),
1831
 
                 ID2SYM(rb_intern("replace")));
1832
 
    ecflags = rb_econv_prepare_opts(opthash, &ecopts);
1833
 
    return rb_str_encode(src, rb_enc_from_encoding(enc), ecflags, ecopts);
 
1873
    return rb_str_encode(src, rb_enc_from_encoding(enc), ECONV_UNDEF_REPLACE, Qnil);
1834
1874
}
1835
1875
 
1836
1876
char *
1888
1928
 
1889
1929
        return &(dirp->dirstr);
1890
1930
 
1891
 
    } else
 
1931
    }
 
1932
    else
1892
1933
        return NULL;
1893
1934
}
1894
1935
 
2154
2195
}
2155
2196
 
2156
2197
//
2157
 
// Since the errors returned by the socket error function 
 
2198
// Since the errors returned by the socket error function
2158
2199
// WSAGetLastError() are not known by the library routine strerror
2159
2200
// we have to roll our own.
2160
2201
//
2196
2237
        }
2197
2238
#endif
2198
2239
        if (FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
 
2240
                          FORMAT_MESSAGE_IGNORE_INSERTS, &source, e,
 
2241
                          MAKELANGID(LANG_ENGLISH, SUBLANG_ENGLISH_US),
 
2242
                          buffer, sizeof(buffer), NULL) == 0 &&
 
2243
            FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
2199
2244
                          FORMAT_MESSAGE_IGNORE_INSERTS, &source, e, 0,
2200
2245
                          buffer, sizeof(buffer), NULL) == 0)
2201
2246
            strlcpy(buffer, "Unknown Error", sizeof(buffer));
2250
2295
 
2251
2296
int
2252
2297
setuid(rb_uid_t uid)
2253
 
 
2298
{
2254
2299
    return (uid == ROOT_UID ? 0 : -1);
2255
2300
}
2256
2301
 
2322
2367
    return ret;
2323
2368
}
2324
2369
 
 
2370
void
 
2371
rb_w32_fd_copy(rb_fdset_t *dst, const fd_set *src, int max)
 
2372
{
 
2373
    max = min(src->fd_count, (UINT)max);
 
2374
    if ((UINT)dst->capa < (UINT)max) {
 
2375
        dst->capa = (src->fd_count / FD_SETSIZE + 1) * FD_SETSIZE;
 
2376
        dst->fdset = xrealloc(dst->fdset, sizeof(unsigned int) + sizeof(SOCKET) * dst->capa);
 
2377
    }
 
2378
 
 
2379
    memcpy(dst->fdset->fd_array, src->fd_array,
 
2380
           max * sizeof(src->fd_array[0]));
 
2381
    dst->fdset->fd_count = src->fd_count;
 
2382
}
 
2383
 
 
2384
/* License: Ruby's */
 
2385
void
 
2386
rb_w32_fd_dup(rb_fdset_t *dst, const rb_fdset_t *src)
 
2387
{
 
2388
    if ((UINT)dst->capa < src->fdset->fd_count) {
 
2389
        dst->capa = (src->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE;
 
2390
        dst->fdset = xrealloc(dst->fdset, sizeof(unsigned int) + sizeof(SOCKET) * dst->capa);
 
2391
    }
 
2392
 
 
2393
    memcpy(dst->fdset->fd_array, src->fdset->fd_array,
 
2394
           src->fdset->fd_count * sizeof(src->fdset->fd_array[0]));
 
2395
    dst->fdset->fd_count = src->fdset->fd_count;
 
2396
}
 
2397
 
2325
2398
//
2326
2399
// Networking trampolines
2327
 
// These are used to avoid socket startup/shutdown overhead in case 
 
2400
// These are used to avoid socket startup/shutdown overhead in case
2328
2401
// the socket routines aren't used.
2329
2402
//
2330
2403
 
2334
2407
extract_fd(rb_fdset_t *dst, fd_set *src, int (*func)(SOCKET))
2335
2408
{
2336
2409
    unsigned int s = 0;
2337
 
    if (!src || !dst) return 0;
 
2410
    unsigned int m = 0;
 
2411
    if (!src) return 0;
2338
2412
 
2339
2413
    while (s < src->fd_count) {
2340
2414
        SOCKET fd = src->fd_array[s];
2341
2415
 
2342
 
        if (!func || (*func)(fd)) { /* move it to dst */
2343
 
            unsigned int d;
 
2416
        if (!func || (*func)(fd)) {
 
2417
            if (dst) { /* move it to dst */
 
2418
                unsigned int d;
2344
2419
 
2345
 
            for (d = 0; d < dst->fdset->fd_count; d++) {
2346
 
                if (dst->fdset->fd_array[d] == fd)
2347
 
                    break;
2348
 
            }
2349
 
            if (d == dst->fdset->fd_count) {
2350
 
                if ((int)dst->fdset->fd_count >= dst->capa) {
2351
 
                    dst->capa = (dst->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE;
2352
 
                    dst->fdset = xrealloc(dst->fdset, sizeof(unsigned int) + sizeof(SOCKET) * dst->capa);
2353
 
                }
2354
 
                dst->fdset->fd_array[dst->fdset->fd_count++] = fd;
2355
 
            }
2356
 
            memmove(
2357
 
                &src->fd_array[s],
2358
 
                &src->fd_array[s+1], 
2359
 
                sizeof(src->fd_array[0]) * (--src->fd_count - s));
 
2420
                for (d = 0; d < dst->fdset->fd_count; d++) {
 
2421
                    if (dst->fdset->fd_array[d] == fd)
 
2422
                        break;
 
2423
                }
 
2424
                if (d == dst->fdset->fd_count) {
 
2425
                    if ((int)dst->fdset->fd_count >= dst->capa) {
 
2426
                        dst->capa = (dst->fdset->fd_count / FD_SETSIZE + 1) * FD_SETSIZE;
 
2427
                        dst->fdset = xrealloc(dst->fdset, sizeof(unsigned int) + sizeof(SOCKET) * dst->capa);
 
2428
                    }
 
2429
                    dst->fdset->fd_array[dst->fdset->fd_count++] = fd;
 
2430
                }
 
2431
                memmove(
 
2432
                    &src->fd_array[s],
 
2433
                    &src->fd_array[s+1],
 
2434
                    sizeof(src->fd_array[0]) * (--src->fd_count - s));
 
2435
            }
 
2436
            else {
 
2437
                m++;
 
2438
                s++;
 
2439
            }
2360
2440
        }
2361
2441
        else s++;
2362
2442
    }
2363
2443
 
2364
 
    return dst->fdset->fd_count;
 
2444
    return dst ? dst->fdset->fd_count : m;
2365
2445
}
2366
2446
 
2367
2447
static int
2458
2538
}
2459
2539
 
2460
2540
static int
 
2541
is_invalid_handle(SOCKET sock)
 
2542
{
 
2543
    return (HANDLE)sock == INVALID_HANDLE_VALUE;
 
2544
}
 
2545
 
 
2546
static int
2461
2547
do_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
2462
2548
            struct timeval *timeout)
2463
2549
{
2484
2570
    return r;
2485
2571
}
2486
2572
 
2487
 
static inline int
2488
 
subtract(struct timeval *rest, const struct timeval *wait)
 
2573
/*
 
2574
 * rest -= wait
 
2575
 * return 0 if rest is smaller than wait.
 
2576
 */
 
2577
int
 
2578
rb_w32_time_subtract(struct timeval *rest, const struct timeval *wait)
2489
2579
{
2490
2580
    if (rest->tv_sec < wait->tv_sec) {
2491
2581
        return 0;
2517
2607
}
2518
2608
 
2519
2609
#undef Sleep
2520
 
int WSAAPI
2521
 
rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
2522
 
              struct timeval *timeout)
 
2610
 
 
2611
int rb_w32_check_interrupt(void *);     /* @internal */
 
2612
 
 
2613
/* @internal */
 
2614
int
 
2615
rb_w32_select_with_thread(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
 
2616
                          struct timeval *timeout, void *th)
2523
2617
{
2524
2618
    int r;
2525
2619
    rb_fdset_t pipe_rd;
2564
2658
    rb_fd_init(&else_rd);
2565
2659
    nonsock += extract_fd(&else_rd, rd, is_not_socket);
2566
2660
 
 
2661
    rb_fd_init(&else_wr);
 
2662
    nonsock += extract_fd(&else_wr, wr, is_not_socket);
 
2663
 
 
2664
    // check invalid handles
 
2665
    if (extract_fd(NULL, else_rd.fdset, is_invalid_handle) > 0 ||
 
2666
        extract_fd(NULL, else_wr.fdset, is_invalid_handle) > 0) {
 
2667
        rb_fd_term(&else_wr);
 
2668
        rb_fd_term(&else_rd);
 
2669
        errno = EBADF;
 
2670
        return -1;
 
2671
    }
 
2672
 
2567
2673
    rb_fd_init(&pipe_rd);
2568
2674
    extract_fd(&pipe_rd, else_rd.fdset, is_pipe); // should not call is_pipe for socket
2569
2675
 
2570
2676
    rb_fd_init(&cons_rd);
2571
2677
    extract_fd(&cons_rd, else_rd.fdset, is_console); // ditto
2572
2678
 
2573
 
    rb_fd_init(&else_wr);
2574
 
    nonsock += extract_fd(&else_wr, wr, is_not_socket);
2575
 
 
2576
2679
    rb_fd_init(&except);
2577
2680
    extract_fd(&except, ex, is_not_socket); // drop only
2578
2681
 
2589
2692
        wait.tv_sec = 0; wait.tv_usec = 10 * 1000; // 10ms
2590
2693
        zero.tv_sec = 0; zero.tv_usec = 0;         //  0ms
2591
2694
        for (;;) {
 
2695
            if (th && rb_w32_check_interrupt(th) != WAIT_TIMEOUT) {
 
2696
                r = -1;
 
2697
                break;
 
2698
            }
2592
2699
            if (nonsock) {
2593
2700
                // modifying {else,pipe,cons}_rd is safe because
2594
2701
                // if they are modified, function returns immediately.
2599
2706
            if (else_rd.fdset->fd_count || else_wr.fdset->fd_count) {
2600
2707
                r = do_select(nfds, rd, wr, ex, &zero); // polling
2601
2708
                if (r < 0) break; // XXX: should I ignore error and return signaled handles?
2602
 
                r = copy_fd(rd, else_rd.fdset);
 
2709
                r += copy_fd(rd, else_rd.fdset);
2603
2710
                r += copy_fd(wr, else_wr.fdset);
2604
2711
                if (ex)
2605
2712
                    r += ex->fd_count;
2624
2731
                    struct timeval now;
2625
2732
                    gettimeofday(&now, NULL);
2626
2733
                    rest = limit;
2627
 
                    if (!subtract(&rest, &now)) break;
 
2734
                    if (!rb_w32_time_subtract(&rest, &now)) break;
2628
2735
                    if (compare(&rest, &wait) < 0) dowait = &rest;
2629
2736
                }
2630
2737
                Sleep(dowait->tv_sec * 1000 + dowait->tv_usec / 1000);
2633
2740
    }
2634
2741
 
2635
2742
    rb_fd_term(&except);
2636
 
    rb_fd_term(&else_wr);
2637
2743
    rb_fd_term(&cons_rd);
2638
2744
    rb_fd_term(&pipe_rd);
 
2745
    rb_fd_term(&else_wr);
2639
2746
    rb_fd_term(&else_rd);
2640
2747
 
2641
2748
    return r;
2642
2749
}
2643
2750
 
 
2751
int WSAAPI
 
2752
rb_w32_select(int nfds, fd_set *rd, fd_set *wr, fd_set *ex,
 
2753
              struct timeval *timeout)
 
2754
{
 
2755
    return rb_w32_select_with_thread(nfds, rd, wr, ex, timeout, 0);
 
2756
}
 
2757
 
 
2758
static FARPROC
 
2759
get_wsa_extension_function(SOCKET s, GUID *guid)
 
2760
{
 
2761
    DWORD dmy;
 
2762
    FARPROC ptr = NULL;
 
2763
 
 
2764
    WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, guid, sizeof(*guid),
 
2765
             &ptr, sizeof(ptr), &dmy, NULL, NULL);
 
2766
    if (!ptr)
 
2767
        errno = ENOSYS;
 
2768
    return ptr;
 
2769
}
 
2770
 
2644
2771
#undef accept
2645
2772
 
2646
2773
int WSAAPI
2806
2933
#undef sendto
2807
2934
 
2808
2935
static int
 
2936
finish_overlapped_socket(SOCKET s, WSAOVERLAPPED *wol, int result, DWORD *len, DWORD size)
 
2937
{
 
2938
    DWORD flg;
 
2939
    int err;
 
2940
 
 
2941
    if (result != SOCKET_ERROR)
 
2942
        *len = size;
 
2943
    else if ((err = WSAGetLastError()) == WSA_IO_PENDING) {
 
2944
        switch (rb_w32_wait_events_blocking(&wol->hEvent, 1, INFINITE)) {
 
2945
          case WAIT_OBJECT_0:
 
2946
            RUBY_CRITICAL(
 
2947
                result = WSAGetOverlappedResult(s, wol, &size, TRUE, &flg)
 
2948
                );
 
2949
            if (result) {
 
2950
                *len = size;
 
2951
                break;
 
2952
            }
 
2953
            /* thru */
 
2954
          default:
 
2955
            errno = map_errno(WSAGetLastError());
 
2956
            /* thru */
 
2957
          case WAIT_OBJECT_0 + 1:
 
2958
            /* interrupted */
 
2959
            *len = -1;
 
2960
            cancel_io((HANDLE)s);
 
2961
            break;
 
2962
        }
 
2963
    }
 
2964
    else {
 
2965
        errno = map_errno(err);
 
2966
        *len = -1;
 
2967
    }
 
2968
    CloseHandle(wol->hEvent);
 
2969
 
 
2970
    return result;
 
2971
}
 
2972
 
 
2973
static int
2809
2974
overlapped_socket_io(BOOL input, int fd, char *buf, int len, int flags,
2810
2975
                     struct sockaddr *addr, int *addrlen)
2811
2976
{
2816
2981
    DWORD flg;
2817
2982
    WSAOVERLAPPED wol;
2818
2983
    WSABUF wbuf;
2819
 
    int err;
2820
2984
    SOCKET s;
2821
2985
 
2822
2986
    if (!NtSocketsInitialized)
2845
3009
    }
2846
3010
    else {
2847
3011
        DWORD size;
 
3012
        DWORD rlen;
2848
3013
        wbuf.len = len;
2849
3014
        wbuf.buf = buf;
2850
3015
        memset(&wol, 0, sizeof(wol));
2867
3032
            }
2868
3033
        });
2869
3034
 
2870
 
        if (ret != SOCKET_ERROR) {
2871
 
            r = size;
2872
 
        }
2873
 
        else if ((err = WSAGetLastError()) == WSA_IO_PENDING) {
2874
 
            switch (rb_w32_wait_events_blocking(&wol.hEvent, 1, INFINITE)) {
2875
 
              case WAIT_OBJECT_0:
2876
 
                RUBY_CRITICAL(
2877
 
                    ret = WSAGetOverlappedResult(s, &wol, &size, TRUE, &flg)
2878
 
                    );
2879
 
                if (ret) {
2880
 
                    r = size;
2881
 
                    break;
2882
 
                }
2883
 
                /* thru */
2884
 
              default:
2885
 
                errno = map_errno(WSAGetLastError());
2886
 
                /* thru */
2887
 
              case WAIT_OBJECT_0 + 1:
2888
 
                /* interrupted */
2889
 
                r = -1;
2890
 
                cancel_io((HANDLE)s);
2891
 
                break;
2892
 
            }
2893
 
        }
2894
 
        else {
2895
 
            errno = map_errno(err);
2896
 
            r = -1;
2897
 
        }
2898
 
        CloseHandle(wol.hEvent);
 
3035
        finish_overlapped_socket(s, &wol, ret, &rlen, size);
 
3036
        r = (int)rlen;
2899
3037
    }
2900
3038
 
2901
3039
    return r;
2921
3059
}
2922
3060
 
2923
3061
int WSAAPI
2924
 
rb_w32_sendto(int fd, const char *buf, int len, int flags, 
 
3062
rb_w32_sendto(int fd, const char *buf, int len, int flags,
2925
3063
              const struct sockaddr *to, int tolen)
2926
3064
{
2927
3065
    return overlapped_socket_io(FALSE, fd, (char *)buf, len, flags,
2980
3118
 
2981
3119
    if (!pWSARecvMsg) {
2982
3120
        static GUID guid = WSAID_WSARECVMSG;
2983
 
        DWORD dmy;
2984
 
        WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
2985
 
                 &pWSARecvMsg, sizeof(pWSARecvMsg), &dmy, NULL, NULL);
2986
 
        if (!pWSARecvMsg) {
2987
 
            errno = ENOSYS;
 
3121
        pWSARecvMsg = (WSARecvMsg_t)get_wsa_extension_function(s, &guid);
 
3122
        if (!pWSARecvMsg)
2988
3123
            return -1;
2989
 
        }
2990
3124
    }
2991
3125
 
2992
3126
    msghdr_to_wsamsg(msg, &wsamsg);
3004
3138
    }
3005
3139
    else {
3006
3140
        DWORD size;
3007
 
        int err;
3008
3141
        WSAOVERLAPPED wol;
3009
3142
        memset(&wol, 0, sizeof(wol));
3010
3143
        RUBY_CRITICAL({
3011
3144
            wol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
3012
 
            ret = pWSARecvMsg(s, &wsamsg, &len, &wol, NULL);
 
3145
            ret = pWSARecvMsg(s, &wsamsg, &size, &wol, NULL);
3013
3146
        });
3014
3147
 
3015
 
        if (ret != SOCKET_ERROR) {
3016
 
            /* nothing to do */
3017
 
        }
3018
 
        else if ((err = WSAGetLastError()) == WSA_IO_PENDING) {
3019
 
            DWORD flg;
3020
 
            switch (rb_w32_wait_events_blocking(&wol.hEvent, 1, INFINITE)) {
3021
 
              case WAIT_OBJECT_0:
3022
 
                RUBY_CRITICAL(
3023
 
                    ret = WSAGetOverlappedResult(s, &wol, &size, TRUE, &flg)
3024
 
                    );
3025
 
                if (ret) {
3026
 
                    len = size;
3027
 
                    break;
3028
 
                }
3029
 
                /* thru */
3030
 
              default:
3031
 
                errno = map_errno(WSAGetLastError());
3032
 
                /* thru */
3033
 
              case WAIT_OBJECT_0 + 1:
3034
 
                /* interrupted */
3035
 
                len = -1;
3036
 
                cancel_io((HANDLE)s);
3037
 
                break;
3038
 
            }
3039
 
        }
3040
 
        else {
3041
 
            errno = map_errno(err);
3042
 
            len = -1;
3043
 
        }
3044
 
        CloseHandle(wol.hEvent);
 
3148
        ret = finish_overlapped_socket(s, &wol, ret, &len, size);
3045
3149
    }
3046
3150
    if (ret == SOCKET_ERROR)
3047
3151
        return -1;
3073
3177
 
3074
3178
    if (!pWSASendMsg) {
3075
3179
        static GUID guid = WSAID_WSASENDMSG;
3076
 
        DWORD dmy;
3077
 
        WSAIoctl(s, SIO_GET_EXTENSION_FUNCTION_POINTER, &guid, sizeof(guid),
3078
 
                 &pWSASendMsg, sizeof(pWSASendMsg), &dmy, NULL, NULL);
3079
 
        if (!pWSASendMsg) {
3080
 
            errno = ENOSYS;
 
3180
        pWSASendMsg = (WSASendMsg_t)get_wsa_extension_function(s, &guid);
 
3181
        if (!pWSASendMsg)
3081
3182
            return -1;
3082
 
        }
3083
3183
    }
3084
3184
 
3085
3185
    msghdr_to_wsamsg(msg, &wsamsg);
3096
3196
    }
3097
3197
    else {
3098
3198
        DWORD size;
3099
 
        int err;
3100
3199
        WSAOVERLAPPED wol;
3101
3200
        memset(&wol, 0, sizeof(wol));
3102
3201
        RUBY_CRITICAL({
3103
3202
            wol.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL);
3104
 
            ret = pWSASendMsg(s, &wsamsg, flags, &len, &wol, NULL);
 
3203
            ret = pWSASendMsg(s, &wsamsg, flags, &size, &wol, NULL);
3105
3204
        });
3106
3205
 
3107
 
        if (ret != SOCKET_ERROR) {
3108
 
            /* nothing to do */
3109
 
        }
3110
 
        else if ((err = WSAGetLastError()) == WSA_IO_PENDING) {
3111
 
            DWORD flg;
3112
 
            switch (rb_w32_wait_events_blocking(&wol.hEvent, 1, INFINITE)) {
3113
 
              case WAIT_OBJECT_0:
3114
 
                RUBY_CRITICAL(
3115
 
                    ret = WSAGetOverlappedResult(s, &wol, &size, TRUE, &flg)
3116
 
                    );
3117
 
                if (ret) {
3118
 
                    len = size;
3119
 
                    break;
3120
 
                }
3121
 
                /* thru */
3122
 
              default:
3123
 
                errno = map_errno(WSAGetLastError());
3124
 
                /* thru */
3125
 
              case WAIT_OBJECT_0 + 1:
3126
 
                /* interrupted */
3127
 
                len = -1;
3128
 
                cancel_io((HANDLE)s);
3129
 
                break;
3130
 
            }
3131
 
        }
3132
 
        else {
3133
 
            errno = map_errno(err);
3134
 
            len = -1;
3135
 
        }
3136
 
        CloseHandle(wol.hEvent);
 
3206
        finish_overlapped_socket(s, &wol, ret, &len, size);
3137
3207
    }
3138
3208
 
3139
3209
    return len;
3155
3225
    });
3156
3226
    return r;
3157
3227
}
3158
 
    
 
3228
 
3159
3229
#undef shutdown
3160
3230
 
3161
3231
int WSAAPI
3599
3669
 
3600
3670
    if (options == WNOHANG) {
3601
3671
        timeout = 0;
3602
 
    } else {
 
3672
    }
 
3673
    else {
3603
3674
        timeout = INFINITE;
3604
3675
    }
3605
3676
 
3792
3863
 
3793
3864
      case SIGKILL:
3794
3865
        RUBY_CRITICAL({
3795
 
            HANDLE hProc = OpenProcess(PROCESS_TERMINATE, FALSE, (DWORD)pid);
 
3866
            HANDLE hProc;
 
3867
            struct ChildRecord* child = FindChildSlot(pid);
 
3868
            if (child) {
 
3869
                hProc = child->hProcess;
 
3870
            }
 
3871
            else {
 
3872
                hProc = OpenProcess(PROCESS_TERMINATE | PROCESS_QUERY_INFORMATION, FALSE, (DWORD)pid);
 
3873
            }
3796
3874
            if (hProc == NULL || hProc == INVALID_HANDLE_VALUE) {
3797
3875
                if (GetLastError() == ERROR_INVALID_PARAMETER) {
3798
3876
                    errno = ESRCH;
3803
3881
                ret = -1;
3804
3882
            }
3805
3883
            else {
3806
 
                if (!TerminateProcess(hProc, 0)) {
3807
 
                    errno = EPERM;
3808
 
                    ret = -1;
3809
 
                }
3810
 
                CloseHandle(hProc);
 
3884
                DWORD status;
 
3885
                if (!GetExitCodeProcess(hProc, &status)) {
 
3886
                    errno = map_errno(GetLastError());
 
3887
                    ret = -1;
 
3888
                }
 
3889
                else if (status == STILL_ACTIVE) {
 
3890
                    if (!TerminateProcess(hProc, 0)) {
 
3891
                        errno = EPERM;
 
3892
                        ret = -1;
 
3893
                    }
 
3894
                }
 
3895
                else {
 
3896
                    errno = ESRCH;
 
3897
                    ret = -1;
 
3898
                }
 
3899
                if (!child) {
 
3900
                    CloseHandle(hProc);
 
3901
                }
3811
3902
            }
3812
3903
        });
3813
3904
        break;
3824
3915
static int
3825
3916
wlink(const WCHAR *from, const WCHAR *to)
3826
3917
{
3827
 
    static BOOL (WINAPI *pCreateHardLinkW)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES) = NULL;
 
3918
    typedef BOOL (WINAPI link_func)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES);
 
3919
    static link_func *pCreateHardLinkW = NULL;
3828
3920
    static int myerrno = 0;
3829
3921
 
3830
3922
    if (!pCreateHardLinkW && !myerrno) {
3831
 
        HANDLE hKernel;
3832
 
 
3833
 
        hKernel = GetModuleHandle("kernel32.dll");
3834
 
        if (hKernel) {
3835
 
            pCreateHardLinkW = (BOOL (WINAPI *)(LPCWSTR, LPCWSTR, LPSECURITY_ATTRIBUTES))GetProcAddress(hKernel, "CreateHardLinkW");
3836
 
            if (!pCreateHardLinkW) {
3837
 
                myerrno = ENOSYS;
3838
 
            }
3839
 
        }
3840
 
        else {
3841
 
            myerrno = map_errno(GetLastError());
3842
 
        }
 
3923
        pCreateHardLinkW = (link_func *)get_proc_address("kernel32", "CreateHardLinkW", NULL);
 
3924
        if (!pCreateHardLinkW)
 
3925
            myerrno = ENOSYS;
3843
3926
    }
3844
3927
    if (!pCreateHardLinkW) {
3845
3928
        errno = myerrno;
3948
4031
                if (IsWinNT()) {
3949
4032
                    if (MoveFileExW(oldpath, newpath, MOVEFILE_REPLACE_EXISTING))
3950
4033
                        res = 0;
3951
 
                } else {
 
4034
                }
 
4035
                else {
3952
4036
                    for (;;) {
3953
4037
                        if (!DeleteFileW(newpath) && GetLastError() != ERROR_FILE_NOT_FOUND)
3954
4038
                            break;
4215
4299
    WCHAR *buf1, *s, *end;
4216
4300
    int len, size;
4217
4301
    int ret;
 
4302
    VALUE v;
4218
4303
 
4219
4304
    if (!path || !st) {
4220
4305
        errno = EFAULT;
4221
4306
        return -1;
4222
4307
    }
4223
4308
    size = lstrlenW(path) + 2;
4224
 
    buf1 = ALLOCA_N(WCHAR, size);
 
4309
    buf1 = ALLOCV_N(WCHAR, v, size);
4225
4310
    for (p = path, s = buf1; *p; p++, s++) {
4226
4311
        if (*p == L'/')
4227
4312
            *s = L'\\';
4249
4334
    if (ret == 0) {
4250
4335
        st->st_mode &= ~(S_IWGRP | S_IWOTH);
4251
4336
    }
 
4337
    if (v)
 
4338
        ALLOCV_END(v);
 
4339
 
4252
4340
    return ret;
4253
4341
}
4254
4342
 
4507
4595
    if (enough_to_get(stream->FILE_COUNT)) {
4508
4596
        c = (unsigned char)*stream->FILE_READPTR++;
4509
4597
    }
4510
 
    else 
4511
 
    {
 
4598
    else {
4512
4599
        c = _filbuf(stream);
4513
4600
#if defined __BORLANDC__
4514
4601
        if ((c == EOF) && (errno == EPIPE)) {
4527
4614
    if (enough_to_put(stream->FILE_COUNT)) {
4528
4615
        c = (unsigned char)(*stream->FILE_READPTR++ = (char)c);
4529
4616
    }
4530
 
    else 
4531
 
    {
 
4617
    else {
4532
4618
        c = _flsbuf(c, stream);
4533
4619
        catch_interrupt();
4534
4620
    }
4680
4766
rb_pid_t
4681
4767
rb_w32_getppid(void)
4682
4768
{
4683
 
    static long (WINAPI *pNtQueryInformationProcess)(HANDLE, int, void *, ULONG, ULONG *) = NULL;
 
4769
    typedef long (WINAPI query_func)(HANDLE, int, void *, ULONG, ULONG *);
 
4770
    static query_func *pNtQueryInformationProcess = NULL;
4684
4771
    rb_pid_t ppid = 0;
4685
4772
 
4686
4773
    if (!IsWin95() && rb_w32_osver() >= 5) {
4687
 
        if (!pNtQueryInformationProcess) {
4688
 
            HANDLE hNtDll = GetModuleHandle("ntdll.dll");
4689
 
            if (hNtDll) {
4690
 
                pNtQueryInformationProcess = (long (WINAPI *)(HANDLE, int, void *, ULONG, ULONG *))GetProcAddress(hNtDll, "NtQueryInformationProcess");
4691
 
            }
4692
 
        }
 
4774
        if (!pNtQueryInformationProcess)
 
4775
            pNtQueryInformationProcess = (query_func *)get_proc_address("ntdll.dll", "NtQueryInformationProcess", NULL);
4693
4776
        if (pNtQueryInformationProcess) {
4694
4777
            struct {
4695
4778
                long ExitStatus;
4696
4779
                void* PebBaseAddress;
4697
 
                ULONG AffinityMask;
4698
 
                ULONG BasePriority;
4699
 
                ULONG UniqueProcessId;
4700
 
                ULONG ParentProcessId;
 
4780
                uintptr_t AffinityMask;
 
4781
                uintptr_t BasePriority;
 
4782
                uintptr_t UniqueProcessId;
 
4783
                uintptr_t ParentProcessId;
4701
4784
            } pbi;
4702
4785
            ULONG len;
4703
4786
            long ret = pNtQueryInformationProcess(GetCurrentProcess(), 0, &pbi, sizeof(pbi), &len);
4956
5039
        return _pipe(fds, 65536L, _O_NOINHERIT);
4957
5040
 
4958
5041
    p = strchr(name, '0');
4959
 
    snprintf(p, strlen(p) + 1, "%x-%lx", rb_w32_getpid(), serial++);
 
5042
    snprintf(p, strlen(p) + 1, "%"PRI_PIDT_PREFIX"x-%lx", rb_w32_getpid(), serial++);
4960
5043
 
4961
5044
    sec.nLength = sizeof(sec);
4962
5045
    sec.lpSecurityDescriptor = NULL;
5057
5140
}
5058
5141
 
5059
5142
#undef read
5060
 
size_t
 
5143
ssize_t
5061
5144
rb_w32_read(int fd, void *buf, size_t size)
5062
5145
{
5063
5146
    SOCKET sock = TO_SOCKET(fd);
5068
5151
    size_t ret;
5069
5152
    OVERLAPPED ol, *pol = NULL;
5070
5153
    BOOL isconsole;
5071
 
    BOOL islineinput;
 
5154
    BOOL islineinput = FALSE;
5072
5155
    int start = 0;
5073
5156
 
5074
5157
    if (is_socket(sock))
5093
5176
 
5094
5177
    ret = 0;
5095
5178
    isconsole = is_console(_osfhnd(fd));
5096
 
    if(isconsole){
 
5179
    if (isconsole) {
5097
5180
        DWORD mode;
5098
5181
        GetConsoleMode((HANDLE)_osfhnd(fd),&mode);
5099
5182
        islineinput = (mode & ENABLE_LINE_INPUT) != 0;
5213
5296
}
5214
5297
 
5215
5298
#undef write
5216
 
size_t
 
5299
ssize_t
5217
5300
rb_w32_write(int fd, const void *buf, size_t size)
5218
5301
{
5219
5302
    SOCKET sock = TO_SOCKET(fd);
5338
5421
    return ret;
5339
5422
}
5340
5423
 
 
5424
long
 
5425
rb_w32_write_console(uintptr_t strarg, int fd)
 
5426
{
 
5427
    static int disable;
 
5428
    HANDLE handle;
 
5429
    DWORD dwMode, reslen;
 
5430
    VALUE str = strarg;
 
5431
 
 
5432
    if (disable) return -1L;
 
5433
    handle = (HANDLE)_osfhnd(fd);
 
5434
    if (!GetConsoleMode(handle, &dwMode) ||
 
5435
        !rb_econv_has_convpath_p(rb_enc_name(rb_enc_get(str)), "UTF-16LE"))
 
5436
        return -1L;
 
5437
 
 
5438
    str = rb_str_encode(str, rb_enc_from_encoding(rb_enc_find("UTF-16LE")),
 
5439
                        ECONV_INVALID_REPLACE|ECONV_UNDEF_REPLACE, Qnil);
 
5440
    if (!WriteConsoleW(handle, (LPWSTR)RSTRING_PTR(str), RSTRING_LEN(str)/2,
 
5441
                       &reslen, NULL)) {
 
5442
        if (GetLastError() == ERROR_CALL_NOT_IMPLEMENTED)
 
5443
            disable = TRUE;
 
5444
        return -1L;
 
5445
    }
 
5446
    return (long)reslen;
 
5447
}
 
5448
 
5341
5449
static int
5342
5450
unixtime_to_filetime(time_t time, FILETIME *ft)
5343
5451
{
5550
5658
        if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
5551
5659
            SetFileAttributesW(path, attr & ~FILE_ATTRIBUTE_READONLY);
5552
5660
        }
5553
 
        if (DeleteFileW(path) == FALSE) {
 
5661
        if (!DeleteFileW(path)) {
5554
5662
            errno = map_errno(GetLastError());
5555
5663
            ret = -1;
5556
5664
            if (attr != (DWORD)-1 && (attr & FILE_ATTRIBUTE_READONLY)) {
5604
5712
int
5605
5713
rb_w32_isatty(int fd)
5606
5714
{
 
5715
    DWORD mode;
 
5716
 
5607
5717
    // validate fd by using _get_osfhandle() because we cannot access _nhandle
5608
5718
    if (_get_osfhandle(fd) == -1) {
5609
5719
        return 0;
5610
5720
    }
5611
 
    if (!(_osfile(fd) & FDEV)) {
 
5721
    if (!GetConsoleMode((HANDLE)_osfhnd(fd), &mode)) {
5612
5722
        errno = ENOTTY;
5613
5723
        return 0;
5614
5724
    }
5690
5800
    return *ip < 0;
5691
5801
}
5692
5802
#endif
 
5803
 
 
5804
char * WSAAPI
 
5805
rb_w32_inet_ntop(int af, void *addr, char *numaddr, size_t numaddr_len)
 
5806
{
 
5807
    typedef char *(WSAAPI inet_ntop_t)(int, void *, char *, size_t);
 
5808
    inet_ntop_t *pInetNtop;
 
5809
    pInetNtop = (inet_ntop_t *)get_proc_address("ws2_32", "inet_ntop", NULL);
 
5810
    if(pInetNtop){
 
5811
       return pInetNtop(af,addr,numaddr,numaddr_len);
 
5812
    }else{
 
5813
       struct in_addr in;
 
5814
       memcpy(&in.s_addr, addr, sizeof(in.s_addr));
 
5815
       snprintf(numaddr, numaddr_len, "%s", inet_ntoa(in));
 
5816
    }
 
5817
    return numaddr;
 
5818
}