/TSRM/tsrm_win32.c
C | 417 lines | 319 code | 77 blank | 21 comment | 70 complexity | db80a4216c7fcb13414b4e7e40877a52 MD5 | raw file
Possible License(s): MPL-2.0-no-copyleft-exception, LGPL-2.1, BSD-3-Clause
- /*
- +----------------------------------------------------------------------+
- | PHP Version 5 |
- +----------------------------------------------------------------------+
- | Copyright (c) 1997-2010 The PHP Group |
- +----------------------------------------------------------------------+
- | This source file is subject to version 3.01 of the PHP license, |
- | that is bundled with this package in the file LICENSE, and is |
- | available through the world-wide-web at the following url: |
- | http://www.php.net/license/3_01.txt |
- | If you did not receive a copy of the PHP license and are unable to |
- | obtain it through the world-wide-web, please send a note to |
- | license@php.net so we can mail you a copy immediately. |
- +----------------------------------------------------------------------+
- | Authors: Daniel Beulshausen <daniel@php4win.de> |
- +----------------------------------------------------------------------+
- */
- /* $Id: tsrm_win32.c 293036 2010-01-03 09:23:27Z sebastian $ */
- #include <stdio.h>
- #include <fcntl.h>
- #include <io.h>
- #include <process.h>
- #include <time.h>
- #define TSRM_INCLUDE_FULL_WINDOWS_HEADERS
- #include "TSRM.h"
- #ifdef TSRM_WIN32
- #include "tsrm_win32.h"
- #ifdef ZTS
- static ts_rsrc_id win32_globals_id;
- #else
- static tsrm_win32_globals win32_globals;
- #endif
- static void tsrm_win32_ctor(tsrm_win32_globals *globals TSRMLS_DC)
- {
- globals->process = NULL;
- globals->shm = NULL;
- globals->process_size = 0;
- globals->shm_size = 0;
- globals->comspec = _strdup((GetVersion()<0x80000000)?"cmd.exe":"command.com");
- }
- static void tsrm_win32_dtor(tsrm_win32_globals *globals TSRMLS_DC)
- {
- shm_pair *ptr;
- if (globals->process) {
- free(globals->process);
- }
- if (globals->shm) {
- for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
- UnmapViewOfFile(ptr->addr);
- CloseHandle(ptr->segment);
- UnmapViewOfFile(ptr->descriptor);
- CloseHandle(ptr->info);
- }
- free(globals->shm);
- }
- free(globals->comspec);
- }
- TSRM_API void tsrm_win32_startup(void)
- {
- #ifdef ZTS
- ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor);
- #else
- tsrm_win32_ctor(&win32_globals TSRMLS_CC);
- #endif
- }
- TSRM_API void tsrm_win32_shutdown(void)
- {
- #ifndef ZTS
- tsrm_win32_dtor(&win32_globals TSRMLS_CC);
- #endif
- }
- TSRM_API int tsrm_win32_access(const char *pathname, int mode)
- {
- if (mode == 1 /*X_OK*/) {
- #if 1
- /* This code is not supported by Windows 98,
- * but we don't support it anymore */
- DWORD type;
- return GetBinaryType(pathname, &type)?0:-1;
- #else
- SHFILEINFO sfi;
- return access(pathname, 0) == 0 &&
- SHGetFileInfo(pathname, 0, &sfi, sizeof(SHFILEINFO), SHGFI_EXETYPE) != 0 ? 0 : -1;
- #endif
- } else {
- return access(pathname, mode);
- }
- }
- static process_pair *process_get(FILE *stream TSRMLS_DC)
- {
- process_pair *ptr;
- process_pair *newptr;
- for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
- if (ptr->stream == stream) {
- break;
- }
- }
- if (ptr < (TWG(process) + TWG(process_size))) {
- return ptr;
- }
- newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
- if (newptr == NULL) {
- return NULL;
- }
- TWG(process) = newptr;
- ptr = newptr + TWG(process_size);
- TWG(process_size)++;
- return ptr;
- }
- static shm_pair *shm_get(int key, void *addr)
- {
- shm_pair *ptr;
- shm_pair *newptr;
- TSRMLS_FETCH();
- for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
- if (!ptr->descriptor) {
- continue;
- }
- if (!addr && ptr->descriptor->shm_perm.key == key) {
- break;
- } else if (ptr->addr == addr) {
- break;
- }
- }
- if (ptr < (TWG(shm) + TWG(shm_size))) {
- return ptr;
- }
- newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
- if (newptr == NULL) {
- return NULL;
- }
- TWG(shm) = newptr;
- ptr = newptr + TWG(shm_size);
- TWG(shm_size)++;
- return ptr;
- }
- static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
- HANDLE copy, self = GetCurrentProcess();
- if (!DuplicateHandle(self, fh, self, ©, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
- return NULL;
- }
- return copy;
- }
- TSRM_API FILE *popen(const char *command, const char *type)
- {
- return popen_ex(command, type, NULL, NULL);
- }
- TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
- {
- FILE *stream = NULL;
- int fno, type_len = strlen(type), read, mode;
- STARTUPINFO startup;
- PROCESS_INFORMATION process;
- SECURITY_ATTRIBUTES security;
- HANDLE in, out;
- process_pair *proc;
- char *cmd;
- int i;
- char *ptype = (char *)type;
- TSRMLS_FETCH();
- if (!type) {
- return NULL;
- }
- /*The following two checks can be removed once we drop XP support */
- type_len = strlen(type);
- if (type_len <1 || type_len > 2) {
- return NULL;
- }
- for (i=0; i < type_len; i++) {
- if (!(*ptype == 'r' || *ptype == 'w' || *ptype == 'b' || *ptype == 't')) {
- return NULL;
- }
- ptype++;
- }
- security.nLength = sizeof(SECURITY_ATTRIBUTES);
- security.bInheritHandle = TRUE;
- security.lpSecurityDescriptor = NULL;
- if (!type_len || !CreatePipe(&in, &out, &security, 2048L)) {
- return NULL;
- }
- memset(&startup, 0, sizeof(STARTUPINFO));
- memset(&process, 0, sizeof(PROCESS_INFORMATION));
- startup.cb = sizeof(STARTUPINFO);
- startup.dwFlags = STARTF_USESTDHANDLES;
- startup.hStdError = GetStdHandle(STD_ERROR_HANDLE);
- read = (type[0] == 'r') ? TRUE : FALSE;
- mode = ((type_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;
- if (read) {
- in = dupHandle(in, FALSE);
- startup.hStdInput = GetStdHandle(STD_INPUT_HANDLE);
- startup.hStdOutput = out;
- } else {
- out = dupHandle(out, FALSE);
- startup.hStdInput = in;
- startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
- }
- cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c "));
- sprintf(cmd, "%s /c %s", TWG(comspec), command);
- if (!CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, NORMAL_PRIORITY_CLASS|CREATE_NO_WINDOW, env, cwd, &startup, &process)) {
- free(cmd);
- return NULL;
- }
- free(cmd);
- CloseHandle(process.hThread);
- proc = process_get(NULL TSRMLS_CC);
- if (read) {
- fno = _open_osfhandle((tsrm_intptr_t)in, _O_RDONLY | mode);
- CloseHandle(out);
- } else {
- fno = _open_osfhandle((tsrm_intptr_t)out, _O_WRONLY | mode);
- CloseHandle(in);
- }
- stream = _fdopen(fno, type);
- proc->prochnd = process.hProcess;
- proc->stream = stream;
- return stream;
- }
- TSRM_API int pclose(FILE *stream)
- {
- DWORD termstat = 0;
- process_pair *process;
- TSRMLS_FETCH();
- if ((process = process_get(stream TSRMLS_CC)) == NULL) {
- return 0;
- }
- fflush(process->stream);
- fclose(process->stream);
- WaitForSingleObject(process->prochnd, INFINITE);
- GetExitCodeProcess(process->prochnd, &termstat);
- process->stream = NULL;
- CloseHandle(process->prochnd);
- return termstat;
- }
- TSRM_API int shmget(int key, int size, int flags)
- {
- shm_pair *shm;
- char shm_segment[26], shm_info[29];
- HANDLE shm_handle, info_handle;
- BOOL created = FALSE;
- if (size < 0) {
- return -1;
- }
- sprintf(shm_segment, "TSRM_SHM_SEGMENT:%d", key);
- sprintf(shm_info, "TSRM_SHM_DESCRIPTOR:%d", key);
- shm_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
- info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
- if ((!shm_handle && !info_handle)) {
- if (flags & IPC_CREAT) {
- shm_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment);
- info_handle = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
- created = TRUE;
- }
- if ((!shm_handle || !info_handle)) {
- return -1;
- }
- } else {
- if (flags & IPC_EXCL) {
- return -1;
- }
- }
- shm = shm_get(key, NULL);
- shm->segment = shm_handle;
- shm->info = info_handle;
- shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
- if (created) {
- shm->descriptor->shm_perm.key = key;
- shm->descriptor->shm_segsz = size;
- shm->descriptor->shm_ctime = time(NULL);
- shm->descriptor->shm_cpid = getpid();
- shm->descriptor->shm_perm.mode = flags;
- shm->descriptor->shm_perm.cuid = shm->descriptor->shm_perm.cgid= 0;
- shm->descriptor->shm_perm.gid = shm->descriptor->shm_perm.uid = 0;
- shm->descriptor->shm_atime = shm->descriptor->shm_dtime = 0;
- shm->descriptor->shm_lpid = shm->descriptor->shm_nattch = 0;
- shm->descriptor->shm_perm.mode = shm->descriptor->shm_perm.seq = 0;
- }
- if (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz ) {
- CloseHandle(shm->segment);
- UnmapViewOfFile(shm->descriptor);
- CloseHandle(shm->info);
- return -1;
- }
- return key;
- }
- TSRM_API void *shmat(int key, const void *shmaddr, int flags)
- {
- shm_pair *shm = shm_get(key, NULL);
- if (!shm->segment) {
- return (void*)-1;
- }
- shm->descriptor->shm_atime = time(NULL);
- shm->descriptor->shm_lpid = getpid();
- shm->descriptor->shm_nattch++;
- shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
- return shm->addr;
- }
- TSRM_API int shmdt(const void *shmaddr)
- {
- shm_pair *shm = shm_get(0, (void*)shmaddr);
- if (!shm->segment) {
- return -1;
- }
- shm->descriptor->shm_dtime = time(NULL);
- shm->descriptor->shm_lpid = getpid();
- shm->descriptor->shm_nattch--;
- return UnmapViewOfFile(shm->addr) ? 0 : -1;
- }
- TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
- shm_pair *shm = shm_get(key, NULL);
- if (!shm->segment) {
- return -1;
- }
- switch (cmd) {
- case IPC_STAT:
- memcpy(buf, shm->descriptor, sizeof(struct shmid_ds));
- return 0;
- case IPC_SET:
- shm->descriptor->shm_ctime = time(NULL);
- shm->descriptor->shm_perm.uid = buf->shm_perm.uid;
- shm->descriptor->shm_perm.gid = buf->shm_perm.gid;
- shm->descriptor->shm_perm.mode = buf->shm_perm.mode;
- return 0;
- case IPC_RMID:
- if (shm->descriptor->shm_nattch < 1) {
- shm->descriptor->shm_perm.key = -1;
- }
- return 0;
- default:
- return -1;
- }
- }
- TSRM_API char *realpath(char *orig_path, char *buffer)
- {
- int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
- if(!ret || ret > _MAX_PATH) {
- return NULL;
- }
- return buffer;
- }
- #endif