Annotation of embedaddon/php/TSRM/tsrm_win32.c, revision 1.1

1.1     ! misho       1: /*
        !             2:    +----------------------------------------------------------------------+
        !             3:    | PHP Version 5                                                        |
        !             4:    +----------------------------------------------------------------------+
        !             5:    | Copyright (c) 1997-2012 The PHP Group                                |
        !             6:    +----------------------------------------------------------------------+
        !             7:    | This source file is subject to version 3.01 of the PHP license,      |
        !             8:    | that is bundled with this package in the file LICENSE, and is        |
        !             9:    | available through the world-wide-web at the following url:           |
        !            10:    | http://www.php.net/license/3_01.txt                                  |
        !            11:    | If you did not receive a copy of the PHP license and are unable to   |
        !            12:    | obtain it through the world-wide-web, please send a note to          |
        !            13:    | license@php.net so we can mail you a copy immediately.               |
        !            14:    +----------------------------------------------------------------------+
        !            15:    | Authors: Daniel Beulshausen <daniel@php4win.de>                      |
        !            16:    +----------------------------------------------------------------------+
        !            17: */
        !            18: 
        !            19: /* $Id: tsrm_win32.c 321634 2012-01-01 13:15:04Z felipe $ */
        !            20: 
        !            21: #include <stdio.h>
        !            22: #include <fcntl.h>
        !            23: #include <io.h>
        !            24: #include <process.h>
        !            25: #include <time.h>
        !            26: #include <errno.h>
        !            27: 
        !            28: #define TSRM_INCLUDE_FULL_WINDOWS_HEADERS
        !            29: #include "SAPI.h"
        !            30: #include "TSRM.h"
        !            31: 
        !            32: #ifdef TSRM_WIN32
        !            33: #include <Sddl.h>
        !            34: #include "tsrm_win32.h"
        !            35: #include "tsrm_virtual_cwd.h"
        !            36: 
        !            37: #ifdef ZTS
        !            38: static ts_rsrc_id win32_globals_id;
        !            39: #else
        !            40: static tsrm_win32_globals win32_globals;
        !            41: #endif
        !            42: 
        !            43: static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC)
        !            44: {
        !            45:        globals->process = NULL;
        !            46:        globals->shm     = NULL;
        !            47:        globals->process_size = 0;
        !            48:        globals->shm_size         = 0;
        !            49:        globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com");
        !            50: 
        !            51:        /* Set it to INVALID_HANDLE_VALUE
        !            52:         * It will be initialized correctly in tsrm_win32_access or set to 
        !            53:         * NULL if no impersonation has been done.
        !            54:         * the impersonated token can't be set here as the impersonation
        !            55:         * will happen later, in fcgi_accept_request (or whatever is the
        !            56:         * SAPI being used).
        !            57:         */
        !            58:        globals->impersonation_token = INVALID_HANDLE_VALUE;
        !            59:        globals->impersonation_token_sid = NULL;
        !            60: }
        !            61: 
        !            62: static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
        !            63: {
        !            64:        shm_pair *ptr;
        !            65: 
        !            66:        if (globals->process) {
        !            67:                free(globals->process);
        !            68:        }
        !            69: 
        !            70:        if (globals->shm) {
        !            71:                for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
        !            72:                        UnmapViewOfFile(ptr->addr);
        !            73:                        CloseHandle(ptr->segment);
        !            74:                        UnmapViewOfFile(ptr->descriptor);
        !            75:                        CloseHandle(ptr->info);
        !            76:                }
        !            77:                free(globals->shm);
        !            78:        }
        !            79: 
        !            80:        free(globals->comspec);
        !            81: 
        !            82:        if (globals->impersonation_token && globals->impersonation_token != INVALID_HANDLE_VALUE        ) {
        !            83:                CloseHandle(globals->impersonation_token);
        !            84:        }
        !            85:        if (globals->impersonation_token_sid) {
        !            86:                free(globals->impersonation_token_sid);
        !            87:        }
        !            88: }
        !            89: 
        !            90: TSRM_API void tsrm_win32_startup(void)
        !            91: {
        !            92: #ifdef ZTS
        !            93:        ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor);
        !            94: #else
        !            95:        tsrm_win32_ctor(&win32_globals TSRMLS_CC);
        !            96: #endif
        !            97: }
        !            98: 
        !            99: TSRM_API void tsrm_win32_shutdown(void)
        !           100: {
        !           101: #ifndef ZTS
        !           102:        tsrm_win32_dtor(&win32_globals TSRMLS_CC);
        !           103: #endif
        !           104: }
        !           105: 
        !           106: char * tsrm_win32_get_path_sid_key(const char *pathname TSRMLS_DC)
        !           107: {
        !           108:        PSID pSid = TWG(impersonation_token_sid);
        !           109:        DWORD sid_len = pSid ? GetLengthSid(pSid) : 0;
        !           110:        TCHAR *ptcSid = NULL;
        !           111:        char *bucket_key = NULL;
        !           112: 
        !           113:        if (!pSid) {
        !           114:                bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, strlen(pathname) + 1);
        !           115:                if (!bucket_key) {
        !           116:                        return NULL;
        !           117:                }
        !           118:                memcpy(bucket_key, pathname, strlen(pathname));
        !           119:                return bucket_key;
        !           120:        }
        !           121: 
        !           122:        if (!ConvertSidToStringSid(pSid, &ptcSid)) {
        !           123:                return NULL;
        !           124:        }
        !           125: 
        !           126:        bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, strlen(pathname) + strlen(ptcSid) + 1);
        !           127:        if (!bucket_key) {
        !           128:                LocalFree(ptcSid);
        !           129:                return NULL;
        !           130:        }
        !           131: 
        !           132:        memcpy(bucket_key, ptcSid, strlen(ptcSid));
        !           133:        memcpy(bucket_key + strlen(ptcSid), pathname, strlen(pathname) + 1);
        !           134: 
        !           135:        LocalFree(ptcSid);
        !           136:        return bucket_key;
        !           137: }
        !           138: 
        !           139: 
        !           140: PSID tsrm_win32_get_token_sid(HANDLE hToken)
        !           141: {
        !           142:        BOOL bSuccess = FALSE;
        !           143:        DWORD dwLength = 0;
        !           144:        PTOKEN_USER pTokenUser = NULL;
        !           145:        PSID sid;
        !           146:        PSID *ppsid = &sid;
        !           147:        DWORD sid_len;
        !           148:        PSID pResultSid = NULL;
        !           149: 
        !           150:        /* Get the actual size of the TokenUser structure */
        !           151:        if (!GetTokenInformation(
        !           152:                        hToken, TokenUser, (LPVOID) pTokenUser, 0, &dwLength))  {
        !           153:                if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
        !           154:                        goto Finished;
        !           155:                }
        !           156: 
        !           157:                pTokenUser = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
        !           158:                if (pTokenUser == NULL) {
        !           159:                        goto Finished;
        !           160:                }
        !           161:        }
        !           162: 
        !           163:        /* and fetch it now */
        !           164:        if (!GetTokenInformation(
        !           165:                hToken, TokenUser, (LPVOID) pTokenUser, dwLength, &dwLength)) {
        !           166:                goto Finished;
        !           167:        }
        !           168: 
        !           169:        sid_len = GetLengthSid(pTokenUser->User.Sid);
        !           170: 
        !           171:        /* ConvertSidToStringSid(pTokenUser->User.Sid, &ptcSidOwner); */
        !           172:        pResultSid = malloc(sid_len);
        !           173:        if (!pResultSid) {
        !           174:                goto Finished;
        !           175:        }
        !           176:        if (!CopySid(sid_len, pResultSid, pTokenUser->User.Sid)) {
        !           177:                goto Finished;
        !           178:        }
        !           179:        HeapFree(GetProcessHeap(), 0, (LPVOID)pTokenUser);
        !           180:        return pResultSid;
        !           181: 
        !           182: Finished:
        !           183:        if (pResultSid) {
        !           184:                free(pResultSid);
        !           185:        }
        !           186:        /* Free the buffer for the token groups. */
        !           187:        if (pTokenUser != NULL) {
        !           188:                HeapFree(GetProcessHeap(), 0, (LPVOID)pTokenUser);
        !           189:        }
        !           190:        return NULL;
        !           191: }
        !           192: 
        !           193: TSRM_API int tsrm_win32_access(const char *pathname, int mode)
        !           194: {
        !           195:        time_t t;
        !           196:        HANDLE thread_token;
        !           197:        PSID token_sid;
        !           198:        SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
        !           199:        GENERIC_MAPPING gen_map = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS };
        !           200:        DWORD priv_set_length = sizeof(PRIVILEGE_SET);
        !           201: 
        !           202:        PRIVILEGE_SET privilege_set = {0};
        !           203:        DWORD sec_desc_length = 0, desired_access = 0, granted_access = 0;
        !           204:        BYTE * psec_desc = NULL;
        !           205:        BOOL fAccess = FALSE;
        !           206: 
        !           207:        BOOL bucket_key_alloc = FALSE;
        !           208:        realpath_cache_bucket * bucket = NULL;
        !           209:        char * real_path = NULL;
        !           210: 
        !           211:        TSRMLS_FETCH();
        !           212: 
        !           213:        if (mode == 1 /*X_OK*/) {
        !           214:                DWORD type;
        !           215:                return GetBinaryType(pathname, &type) ? 0 : -1;
        !           216:        } else {
        !           217:                if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) {
        !           218:                        real_path = (char *)malloc(MAX_PATH);
        !           219:                        if(tsrm_realpath(pathname, real_path TSRMLS_CC) == NULL) {
        !           220:                                goto Finished;
        !           221:                        }
        !           222:                        pathname = real_path;
        !           223:                }
        !           224: 
        !           225:                if(access(pathname, mode)) {
        !           226:                        free(real_path);
        !           227:                        return errno;
        !           228:                }
        !           229: 
        !           230:                /* If only existence check is made, return now */
        !           231:                if (mode == 0) {
        !           232:                        free(real_path);
        !           233:                        return 0;
        !           234:                }
        !           235: 
        !           236: /* Only in NTS when impersonate==1 (aka FastCGI) */
        !           237: 
        !           238:                /*
        !           239:                 AccessCheck() requires an impersonation token.  We first get a primary
        !           240:                 token and then create a duplicate impersonation token.  The
        !           241:                 impersonation token is not actually assigned to the thread, but is
        !           242:                 used in the call to AccessCheck.  Thus, this function itself never
        !           243:                 impersonates, but does use the identity of the thread.  If the thread
        !           244:                 was impersonating already, this function uses that impersonation context.
        !           245:                */
        !           246:                if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
        !           247:                        DWORD err = GetLastError();
        !           248:                        if (GetLastError() == ERROR_NO_TOKEN) {
        !           249:                                if (!OpenProcessToken(GetCurrentProcess(), TOKEN_ALL_ACCESS, &thread_token)) {
        !           250:                                         TWG(impersonation_token) = NULL;
        !           251:                                         goto Finished;
        !           252:                                 }
        !           253:                        }
        !           254:                }
        !           255: 
        !           256:                /* token_sid will be freed in tsrmwin32_dtor */
        !           257:                token_sid = tsrm_win32_get_token_sid(thread_token);
        !           258:                if (!token_sid) {
        !           259:                        if (TWG(impersonation_token_sid)) {
        !           260:                                free(TWG(impersonation_token_sid));
        !           261:                        }
        !           262:                        TWG(impersonation_token_sid) = NULL;
        !           263:                        goto Finished;
        !           264:                }
        !           265: 
        !           266:                /* Different identity, we need a new impersontated token as well */
        !           267:                if (!TWG(impersonation_token_sid) || !EqualSid(token_sid, TWG(impersonation_token_sid))) {
        !           268:                        if (TWG(impersonation_token_sid)) {
        !           269:                                free(TWG(impersonation_token_sid));
        !           270:                        }
        !           271:                        TWG(impersonation_token_sid) = token_sid;
        !           272: 
        !           273:                        /* Duplicate the token as impersonated token */
        !           274:                        if (!DuplicateToken(thread_token, SecurityImpersonation, &TWG(impersonation_token))) {
        !           275:                                goto Finished;
        !           276:                        }
        !           277:                } else {
        !           278:                        /* we already have it, free it then */
        !           279:                        free(token_sid);
        !           280:                }
        !           281: 
        !           282:                if (CWDG(realpath_cache_size_limit)) {
        !           283:                        t = time(0);
        !           284:                        bucket = realpath_cache_lookup(pathname, strlen(pathname), t TSRMLS_CC);
        !           285:                        if(bucket == NULL && real_path == NULL) {
        !           286:                                /* We used the pathname directly. Call tsrm_realpath */
        !           287:                                /* so that entry is created in realpath cache */
        !           288:                                real_path = (char *)malloc(MAX_PATH);
        !           289:                                if(tsrm_realpath(pathname, real_path TSRMLS_CC) != NULL) {
        !           290:                                        pathname = real_path;
        !           291:                                        bucket = realpath_cache_lookup(pathname, strlen(pathname), t TSRMLS_CC);
        !           292:                                }
        !           293:                        }
        !           294:                }
        !           295: 
        !           296:                /* Do a full access check because access() will only check read-only attribute */
        !           297:                if(mode == 0 || mode > 6) {
        !           298:                        if(bucket != NULL && bucket->is_rvalid) {
        !           299:                                fAccess = bucket->is_readable;
        !           300:                                goto Finished;
        !           301:                        }
        !           302:                        desired_access = FILE_GENERIC_READ;
        !           303:                } else if(mode <= 2) {
        !           304:                        if(bucket != NULL && bucket->is_wvalid) {
        !           305:                                fAccess = bucket->is_writable;
        !           306:                                goto Finished;
        !           307:                        }
        !           308:                        desired_access = FILE_GENERIC_WRITE;
        !           309:                } else if(mode <= 4) {
        !           310:                        if(bucket != NULL && bucket->is_rvalid) {
        !           311:                                fAccess = bucket->is_readable;
        !           312:                                goto Finished;
        !           313:                        }
        !           314:                        desired_access = FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS;
        !           315:                } else { // if(mode <= 6)
        !           316:                        if(bucket != NULL && bucket->is_rvalid && bucket->is_wvalid) {
        !           317:                                fAccess = bucket->is_readable & bucket->is_writable;
        !           318:                                goto Finished;
        !           319:                        }
        !           320:                        desired_access = FILE_GENERIC_READ | FILE_GENERIC_WRITE;
        !           321:                }
        !           322: 
        !           323:                if(TWG(impersonation_token) == NULL) {
        !           324:                        goto Finished;
        !           325:                }
        !           326: 
        !           327:                /* Get size of security buffer. Call is expected to fail */
        !           328:                if(GetFileSecurity(pathname, sec_info, NULL, 0, &sec_desc_length)) {
        !           329:                        goto Finished;
        !           330:                }
        !           331: 
        !           332:                psec_desc = (BYTE *)malloc(sec_desc_length);
        !           333:                if(psec_desc == NULL ||
        !           334:                         !GetFileSecurity(pathname, sec_info, (PSECURITY_DESCRIPTOR)psec_desc, sec_desc_length, &sec_desc_length)) {
        !           335:                        goto Finished;
        !           336:                }
        !           337: 
        !           338:                MapGenericMask(&desired_access, &gen_map);
        !           339: 
        !           340:                if(!AccessCheck((PSECURITY_DESCRIPTOR)psec_desc, TWG(impersonation_token), desired_access, &gen_map, &privilege_set, &priv_set_length, &granted_access, &fAccess)) {
        !           341:                        goto Finished_Impersonate;
        !           342:                }
        !           343: 
        !           344:                /* Keep the result in realpath_cache */
        !           345:                if(bucket != NULL) {
        !           346:                        if(desired_access == (FILE_GENERIC_READ|FILE_FLAG_BACKUP_SEMANTICS)) {
        !           347:                                bucket->is_rvalid = 1;
        !           348:                                bucket->is_readable = fAccess;
        !           349:                        }
        !           350:                        else if(desired_access == FILE_GENERIC_WRITE) {
        !           351:                                bucket->is_wvalid = 1;
        !           352:                                bucket->is_writable = fAccess;
        !           353:                        } else if (desired_access == (FILE_GENERIC_READ | FILE_GENERIC_WRITE)) {
        !           354:                                bucket->is_rvalid = 1;
        !           355:                                bucket->is_readable = fAccess;
        !           356:                                bucket->is_wvalid = 1;
        !           357:                                bucket->is_writable = fAccess;
        !           358:                        }
        !           359:                }
        !           360: 
        !           361: Finished_Impersonate:
        !           362:                if(psec_desc != NULL) {
        !           363:                        free(psec_desc);
        !           364:                        psec_desc = NULL;
        !           365:                }
        !           366: 
        !           367: Finished:
        !           368:                if(real_path != NULL) {
        !           369:                        free(real_path);
        !           370:                        real_path = NULL;
        !           371:                }
        !           372: 
        !           373:                if(fAccess == FALSE) {
        !           374:                        errno = EACCES;
        !           375:                        return errno;
        !           376:                } else {
        !           377:                        return 0;
        !           378:                }
        !           379:        }
        !           380: }
        !           381: 
        !           382: 
        !           383: static process_pair *process_get(FILE *stream TSRMLS_DC)
        !           384: {
        !           385:        process_pair *ptr;
        !           386:        process_pair *newptr;
        !           387: 
        !           388:        for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
        !           389:                if (ptr->stream == stream) {
        !           390:                        break;
        !           391:                }
        !           392:        }
        !           393: 
        !           394:        if (ptr < (TWG(process) + TWG(process_size))) {
        !           395:                return ptr;
        !           396:        }
        !           397: 
        !           398:        newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
        !           399:        if (newptr == NULL) {
        !           400:                return NULL;
        !           401:        }
        !           402: 
        !           403:        TWG(process) = newptr;
        !           404:        ptr = newptr + TWG(process_size);
        !           405:        TWG(process_size)++;
        !           406:        return ptr;
        !           407: }
        !           408: 
        !           409: static shm_pair *shm_get(int key, void *addr)
        !           410: {
        !           411:        shm_pair *ptr;
        !           412:        shm_pair *newptr;
        !           413:        TSRMLS_FETCH();
        !           414: 
        !           415:        for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
        !           416:                if (!ptr->descriptor) {
        !           417:                        continue;
        !           418:                }
        !           419:                if (!addr && ptr->descriptor->shm_perm.key == key) {
        !           420:                        break;
        !           421:                } else if (ptr->addr == addr) {
        !           422:                        break;
        !           423:                }
        !           424:        }
        !           425: 
        !           426:        if (ptr < (TWG(shm) + TWG(shm_size))) {
        !           427:                return ptr;
        !           428:        }
        !           429: 
        !           430:        newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
        !           431:        if (newptr == NULL) {
        !           432:                return NULL;
        !           433:        }
        !           434: 
        !           435:        TWG(shm) = newptr;
        !           436:        ptr = newptr + TWG(shm_size);
        !           437:        TWG(shm_size)++;
        !           438:        return ptr;
        !           439: }
        !           440: 
        !           441: static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
        !           442:        HANDLE copy, self = GetCurrentProcess();
        !           443:        if (!DuplicateHandle(self, fh, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
        !           444:                return NULL;
        !           445:        }
        !           446:        return copy;
        !           447: }
        !           448: 
        !           449: TSRM_API FILE *popen(const char *command, const char *type)
        !           450: {
        !           451:        return popen_ex(command, type, NULL, NULL);
        !           452: }
        !           453: 
        !           454: TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
        !           455: {
        !           456:        FILE *stream = NULL;
        !           457:        int fno, type_len = strlen(type), read, mode;
        !           458:        STARTUPINFO startup;
        !           459:        PROCESS_INFORMATION process;
        !           460:        SECURITY_ATTRIBUTES security;
        !           461:        HANDLE in, out;
        !           462:        DWORD dwCreateFlags = 0;
        !           463:        BOOL res;
        !           464:        process_pair *proc;
        !           465:        char *cmd;
        !           466:        int i;
        !           467:        char *ptype = (char *)type;
        !           468:        HANDLE thread_token = NULL;
        !           469:        HANDLE token_user = NULL;
        !           470:        BOOL asuser = TRUE;
        !           471: 
        !           472:        TSRMLS_FETCH();
        !           473: 
        !           474:        if (!type) {
        !           475:                return NULL;
        !           476:        }
        !           477: 
        !           478:        /*The following two checks can be removed once we drop XP support */
        !           479:        type_len = strlen(type);
        !           480:        if (type_len <1 || type_len > 2) {
        !           481:                return NULL;
        !           482:        }
        !           483: 
        !           484:        for (i=0; i < type_len; i++) {
        !           485:                if (!(*ptype == 'r' || *ptype == 'w' || *ptype == 'b' || *ptype == 't')) {
        !           486:                        return NULL;
        !           487:                }
        !           488:                ptype++;
        !           489:        }
        !           490: 
        !           491:        security.nLength                                = sizeof(SECURITY_ATTRIBUTES);
        !           492:        security.bInheritHandle                 = TRUE;
        !           493:        security.lpSecurityDescriptor   = NULL;
        !           494: 
        !           495:        if (!type_len || !CreatePipe(&in, &out, &security, 2048L)) {
        !           496:                return NULL;
        !           497:        }
        !           498: 
        !           499:        memset(&startup, 0, sizeof(STARTUPINFO));
        !           500:        memset(&process, 0, sizeof(PROCESS_INFORMATION));
        !           501: 
        !           502:        startup.cb                      = sizeof(STARTUPINFO);
        !           503:        startup.dwFlags         = STARTF_USESTDHANDLES;
        !           504:        startup.hStdError       = GetStdHandle(STD_ERROR_HANDLE);
        !           505: 
        !           506:        read = (type[0] == 'r') ? TRUE : FALSE;
        !           507:        mode = ((type_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;
        !           508: 
        !           509:        if (read) {
        !           510:                in = dupHandle(in, FALSE);
        !           511:                startup.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
        !           512:                startup.hStdOutput = out;
        !           513:        } else {
        !           514:                out = dupHandle(out, FALSE);
        !           515:                startup.hStdInput  = in;
        !           516:                startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
        !           517:        }
        !           518: 
        !           519:        dwCreateFlags = NORMAL_PRIORITY_CLASS;
        !           520:        if (strcmp(sapi_module.name, "cli") != 0) {
        !           521:                dwCreateFlags |= CREATE_NO_WINDOW;
        !           522:        }
        !           523: 
        !           524:        /* Get a token with the impersonated user. */
        !           525:        if(OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
        !           526:                DuplicateTokenEx(thread_token, MAXIMUM_ALLOWED, &security, SecurityImpersonation, TokenPrimary, &token_user);
        !           527:        } else {
        !           528:                DWORD err = GetLastError();
        !           529:                if (err == ERROR_NO_TOKEN) {
        !           530:                        asuser = FALSE;
        !           531:                }
        !           532:        }
        !           533: 
        !           534:        cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")+2);
        !           535:        if (!cmd) {
        !           536:                return NULL;
        !           537:        }
        !           538: 
        !           539:        sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command);
        !           540:        if (asuser) {
        !           541:                res = CreateProcessAsUser(token_user, NULL, cmd, &security, &security, security.bInheritHandle, dwCreateFlags, env, cwd, &startup, &process);
        !           542:                CloseHandle(token_user);
        !           543:        } else {
        !           544:                res = CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, dwCreateFlags, env, cwd, &startup, &process);
        !           545:        }
        !           546:        free(cmd);
        !           547: 
        !           548:        if (!res) {
        !           549:                return NULL;
        !           550:        }
        !           551: 
        !           552:        CloseHandle(process.hThread);
        !           553:        proc = process_get(NULL TSRMLS_CC);
        !           554: 
        !           555:        if (read) {
        !           556:                fno = _open_osfhandle((tsrm_intptr_t)in, _O_RDONLY | mode);
        !           557:                CloseHandle(out);
        !           558:        } else {
        !           559:                fno = _open_osfhandle((tsrm_intptr_t)out, _O_WRONLY | mode);
        !           560:                CloseHandle(in);
        !           561:        }
        !           562: 
        !           563:        stream = _fdopen(fno, type);
        !           564:        proc->prochnd = process.hProcess;
        !           565:        proc->stream = stream;
        !           566:        return stream;
        !           567: }
        !           568: 
        !           569: TSRM_API int pclose(FILE *stream)
        !           570: {
        !           571:        DWORD termstat = 0;
        !           572:        process_pair *process;
        !           573:        TSRMLS_FETCH();
        !           574: 
        !           575:        if ((process = process_get(stream TSRMLS_CC)) == NULL) {
        !           576:                return 0;
        !           577:        }
        !           578: 
        !           579:        fflush(process->stream);
        !           580:        fclose(process->stream);
        !           581: 
        !           582:        WaitForSingleObject(process->prochnd, INFINITE);
        !           583:        GetExitCodeProcess(process->prochnd, &termstat);
        !           584:        process->stream = NULL;
        !           585:        CloseHandle(process->prochnd);
        !           586: 
        !           587:        return termstat;
        !           588: }
        !           589: 
        !           590: TSRM_API int shmget(int key, int size, int flags)
        !           591: {
        !           592:        shm_pair *shm;
        !           593:        char shm_segment[26], shm_info[29];
        !           594:        HANDLE shm_handle, info_handle;
        !           595:        BOOL created = FALSE;
        !           596: 
        !           597:        if (size < 0) {
        !           598:                return -1;
        !           599:        }
        !           600: 
        !           601:        sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key);
        !           602:        sprintf(shm_info, "TSRM_SHM_DESCRIPTOR:%d", key);
        !           603: 
        !           604:        shm_handle  = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
        !           605:        info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
        !           606: 
        !           607:        if ((!shm_handle && !info_handle)) {
        !           608:                if (flags & IPC_CREAT) {
        !           609:                        shm_handle      = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment);
        !           610:                        info_handle     = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
        !           611:                        created         = TRUE;
        !           612:                }
        !           613:                if ((!shm_handle || !info_handle)) {
        !           614:                        return -1;
        !           615:                }
        !           616:        } else {
        !           617:                if (flags & IPC_EXCL) {
        !           618:                        return -1;
        !           619:                }
        !           620:        }
        !           621: 
        !           622:        shm = shm_get(key, NULL);
        !           623:        shm->segment = shm_handle;
        !           624:        shm->info        = info_handle;
        !           625:        shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
        !           626: 
        !           627:        if (created) {
        !           628:                shm->descriptor->shm_perm.key   = key;
        !           629:                shm->descriptor->shm_segsz              = size;
        !           630:                shm->descriptor->shm_ctime              = time(NULL);
        !           631:                shm->descriptor->shm_cpid               = getpid();
        !           632:                shm->descriptor->shm_perm.mode  = flags;
        !           633: 
        !           634:                shm->descriptor->shm_perm.cuid  = shm->descriptor->shm_perm.cgid= 0;
        !           635:                shm->descriptor->shm_perm.gid   = shm->descriptor->shm_perm.uid = 0;
        !           636:                shm->descriptor->shm_atime              = shm->descriptor->shm_dtime    = 0;
        !           637:                shm->descriptor->shm_lpid               = shm->descriptor->shm_nattch   = 0;
        !           638:                shm->descriptor->shm_perm.mode  = shm->descriptor->shm_perm.seq = 0;
        !           639:        }
        !           640: 
        !           641:        if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) {
        !           642:                CloseHandle(shm->segment);
        !           643:                UnmapViewOfFile(shm->descriptor);
        !           644:                CloseHandle(shm->info);
        !           645:                return -1;
        !           646:        }
        !           647: 
        !           648:        return key;
        !           649: }
        !           650: 
        !           651: TSRM_API void *shmat(int key, const void *shmaddr, int flags)
        !           652: {
        !           653:        shm_pair *shm = shm_get(key, NULL);
        !           654: 
        !           655:        if (!shm->segment) {
        !           656:                return (void*)-1;
        !           657:        }
        !           658: 
        !           659:        shm->descriptor->shm_atime = time(NULL);
        !           660:        shm->descriptor->shm_lpid  = getpid();
        !           661:        shm->descriptor->shm_nattch++;
        !           662: 
        !           663:        shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
        !           664: 
        !           665:        return shm->addr;
        !           666: }
        !           667: 
        !           668: TSRM_API int shmdt(const void *shmaddr)
        !           669: {
        !           670:        shm_pair *shm = shm_get(0, (void*)shmaddr);
        !           671: 
        !           672:        if (!shm->segment) {
        !           673:                return -1;
        !           674:        }
        !           675: 
        !           676:        shm->descriptor->shm_dtime = time(NULL);
        !           677:        shm->descriptor->shm_lpid  = getpid();
        !           678:        shm->descriptor->shm_nattch--;
        !           679: 
        !           680:        return UnmapViewOfFile(shm->addr) ? 0 : -1;
        !           681: }
        !           682: 
        !           683: TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
        !           684:        shm_pair *shm = shm_get(key, NULL);
        !           685: 
        !           686:        if (!shm->segment) {
        !           687:                return -1;
        !           688:        }
        !           689: 
        !           690:        switch (cmd) {
        !           691:                case IPC_STAT:
        !           692:                        memcpy(buf, shm->descriptor, sizeof(struct shmid_ds));
        !           693:                        return 0;
        !           694: 
        !           695:                case IPC_SET:
        !           696:                        shm->descriptor->shm_ctime              = time(NULL);
        !           697:                        shm->descriptor->shm_perm.uid   = buf->shm_perm.uid;
        !           698:                        shm->descriptor->shm_perm.gid   = buf->shm_perm.gid;
        !           699:                        shm->descriptor->shm_perm.mode  = buf->shm_perm.mode;
        !           700:                        return 0;
        !           701: 
        !           702:                case IPC_RMID:
        !           703:                        if (shm->descriptor->shm_nattch < 1) {
        !           704:                                shm->descriptor->shm_perm.key = -1;
        !           705:                        }
        !           706:                        return 0;
        !           707: 
        !           708:                default:
        !           709:                        return -1;
        !           710:        }
        !           711: }
        !           712: 
        !           713: TSRM_API char *realpath(char *orig_path, char *buffer)
        !           714: {
        !           715:        int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
        !           716:        if(!ret || ret > _MAX_PATH) {
        !           717:                return NULL;
        !           718:        }
        !           719:        return buffer;
        !           720: }
        !           721: 
        !           722: #endif

FreeBSD-CVSweb <freebsd-cvsweb@FreeBSD.org>