root/TSRM/tsrm_win32.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. tsrm_win32_ctor
  2. tsrm_win32_dtor
  3. tsrm_win32_startup
  4. tsrm_win32_shutdown
  5. tsrm_win32_get_path_sid_key
  6. tsrm_win32_get_token_sid
  7. tsrm_win32_access
  8. process_get
  9. shm_get
  10. dupHandle
  11. popen
  12. popen_ex
  13. pclose
  14. shmget
  15. shmat
  16. shmdt
  17. shmctl
  18. realpath
  19. UnixTimeToFileTime
  20. win32_utime

   1 /*
   2    +----------------------------------------------------------------------+
   3    | PHP Version 7                                                        |
   4    +----------------------------------------------------------------------+
   5    | Copyright (c) 1997-2016 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$ */
  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 "zend_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)
  44 {
  45 #ifdef ZTS
  46 TSRMLS_CACHE_UPDATE();
  47 #endif
  48         globals->process = NULL;
  49         globals->shm     = NULL;
  50         globals->process_size = 0;
  51         globals->shm_size         = 0;
  52         globals->comspec = _strdup("cmd.exe");
  53 
  54         /* Set it to INVALID_HANDLE_VALUE
  55          * It will be initialized correctly in tsrm_win32_access or set to
  56          * NULL if no impersonation has been done.
  57          * the impersonated token can't be set here as the impersonation
  58          * will happen later, in fcgi_accept_request (or whatever is the
  59          * SAPI being used).
  60          */
  61         globals->impersonation_token = INVALID_HANDLE_VALUE;
  62         globals->impersonation_token_sid = NULL;
  63 }
  64 
  65 static void tsrm_win32_dtor(tsrm_win32_globals *globals)
  66 {
  67         shm_pair *ptr;
  68 
  69         if (globals->process) {
  70                 free(globals->process);
  71         }
  72 
  73         if (globals->shm) {
  74                 for (ptr = globals->shm; ptr < (globals->shm + globals->shm_size); ptr++) {
  75                         UnmapViewOfFile(ptr->addr);
  76                         CloseHandle(ptr->segment);
  77                         UnmapViewOfFile(ptr->descriptor);
  78                         CloseHandle(ptr->info);
  79                 }
  80                 free(globals->shm);
  81         }
  82 
  83         free(globals->comspec);
  84 
  85         if (globals->impersonation_token && globals->impersonation_token != INVALID_HANDLE_VALUE        ) {
  86                 CloseHandle(globals->impersonation_token);
  87         }
  88         if (globals->impersonation_token_sid) {
  89                 free(globals->impersonation_token_sid);
  90         }
  91 }
  92 
  93 TSRM_API void tsrm_win32_startup(void)
  94 {
  95 #ifdef ZTS
  96         ts_allocate_id(&win32_globals_id, sizeof(tsrm_win32_globals), (ts_allocate_ctor)tsrm_win32_ctor, (ts_allocate_ctor)tsrm_win32_dtor);
  97 #else
  98         tsrm_win32_ctor(&win32_globals);
  99 #endif
 100 }
 101 
 102 TSRM_API void tsrm_win32_shutdown(void)
 103 {
 104 #ifndef ZTS
 105         tsrm_win32_dtor(&win32_globals);
 106 #endif
 107 }
 108 
 109 char * tsrm_win32_get_path_sid_key(const char *pathname)
 110 {
 111         PSID pSid = TWG(impersonation_token_sid);
 112         TCHAR *ptcSid = NULL;
 113         char *bucket_key = NULL;
 114         size_t ptc_sid_len, pathname_len;
 115 
 116         pathname_len = strlen(pathname);
 117 
 118         if (!pSid) {
 119                 bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pathname_len + 1);
 120                 if (!bucket_key) {
 121                         return NULL;
 122                 }
 123                 memcpy(bucket_key, pathname, pathname_len);
 124                 return bucket_key;
 125         }
 126 
 127         if (!ConvertSidToStringSid(pSid, &ptcSid)) {
 128                 return NULL;
 129         }
 130 
 131 
 132         ptc_sid_len = strlen(ptcSid);
 133         bucket_key = (char *)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, pathname_len + ptc_sid_len + 1);
 134         if (!bucket_key) {
 135                 LocalFree(ptcSid);
 136                 return NULL;
 137         }
 138 
 139         memcpy(bucket_key, ptcSid, ptc_sid_len);
 140         memcpy(bucket_key + ptc_sid_len, pathname, pathname_len + 1);
 141 
 142         LocalFree(ptcSid);
 143         return bucket_key;
 144 }
 145 
 146 
 147 PSID tsrm_win32_get_token_sid(HANDLE hToken)
 148 {
 149         DWORD dwLength = 0;
 150         PTOKEN_USER pTokenUser = NULL;
 151         DWORD sid_len;
 152         PSID pResultSid = NULL;
 153 
 154         /* Get the actual size of the TokenUser structure */
 155         if (!GetTokenInformation(
 156                         hToken, TokenUser, (LPVOID) pTokenUser, 0, &dwLength))  {
 157                 if (GetLastError() != ERROR_INSUFFICIENT_BUFFER) {
 158                         goto Finished;
 159                 }
 160 
 161                 pTokenUser = (PTOKEN_USER)HeapAlloc(GetProcessHeap(), HEAP_ZERO_MEMORY, dwLength);
 162                 if (pTokenUser == NULL) {
 163                         goto Finished;
 164                 }
 165         }
 166 
 167         /* and fetch it now */
 168         if (!GetTokenInformation(
 169                 hToken, TokenUser, (LPVOID) pTokenUser, dwLength, &dwLength)) {
 170                 goto Finished;
 171         }
 172 
 173         sid_len = GetLengthSid(pTokenUser->User.Sid);
 174 
 175         /* ConvertSidToStringSid(pTokenUser->User.Sid, &ptcSidOwner); */
 176         pResultSid = malloc(sid_len);
 177         if (!pResultSid) {
 178                 goto Finished;
 179         }
 180         if (!CopySid(sid_len, pResultSid, pTokenUser->User.Sid)) {
 181                 goto Finished;
 182         }
 183         HeapFree(GetProcessHeap(), 0, (LPVOID)pTokenUser);
 184         return pResultSid;
 185 
 186 Finished:
 187         if (pResultSid) {
 188                 free(pResultSid);
 189         }
 190         /* Free the buffer for the token groups. */
 191         if (pTokenUser != NULL) {
 192                 HeapFree(GetProcessHeap(), 0, (LPVOID)pTokenUser);
 193         }
 194         return NULL;
 195 }
 196 
 197 TSRM_API int tsrm_win32_access(const char *pathname, int mode)
 198 {
 199         time_t t;
 200         HANDLE thread_token = NULL;
 201         PSID token_sid;
 202         SECURITY_INFORMATION sec_info = OWNER_SECURITY_INFORMATION | GROUP_SECURITY_INFORMATION | DACL_SECURITY_INFORMATION;
 203         GENERIC_MAPPING gen_map = { FILE_GENERIC_READ, FILE_GENERIC_WRITE, FILE_GENERIC_EXECUTE, FILE_ALL_ACCESS };
 204         DWORD priv_set_length = sizeof(PRIVILEGE_SET);
 205 
 206         PRIVILEGE_SET privilege_set = {0};
 207         DWORD sec_desc_length = 0, desired_access = 0, granted_access = 0;
 208         BYTE * psec_desc = NULL;
 209         BOOL fAccess = FALSE;
 210 
 211         realpath_cache_bucket * bucket = NULL;
 212         char * real_path = NULL;
 213 
 214         if (mode == 1 /*X_OK*/) {
 215                 DWORD type;
 216                 return GetBinaryType(pathname, &type) ? 0 : -1;
 217         } else {
 218                 if(!IS_ABSOLUTE_PATH(pathname, strlen(pathname)+1)) {
 219                         real_path = (char *)malloc(MAX_PATH);
 220                         if(tsrm_realpath(pathname, real_path) == NULL) {
 221                                 goto Finished;
 222                         }
 223                         pathname = real_path;
 224                 }
 225 
 226                 if(access(pathname, mode)) {
 227                         free(real_path);
 228                         return errno;
 229                 }
 230 
 231                 /* If only existence check is made, return now */
 232                 if (mode == 0) {
 233                         free(real_path);
 234                         return 0;
 235                 }
 236 
 237 /* Only in NTS when impersonate==1 (aka FastCGI) */
 238 
 239                 /*
 240                  AccessCheck() requires an impersonation token.  We first get a primary
 241                  token and then create a duplicate impersonation token.  The
 242                  impersonation token is not actually assigned to the thread, but is
 243                  used in the call to AccessCheck.  Thus, this function itself never
 244                  impersonates, but does use the identity of the thread.  If the thread
 245                  was impersonating already, this function uses that impersonation context.
 246                 */
 247                 if(!OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
 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, (int)strlen(pathname), t);
 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) != NULL) {
 290                                         pathname = real_path;
 291                                         bucket = realpath_cache_lookup(pathname, (int)strlen(pathname), t);
 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(thread_token != NULL) {
 369                         CloseHandle(thread_token);
 370                 }
 371                 if(real_path != NULL) {
 372                         free(real_path);
 373                         real_path = NULL;
 374                 }
 375 
 376                 if(fAccess == FALSE) {
 377                         errno = EACCES;
 378                         return errno;
 379                 } else {
 380                         return 0;
 381                 }
 382         }
 383 }
 384 
 385 
 386 static process_pair *process_get(FILE *stream)
 387 {
 388         process_pair *ptr;
 389         process_pair *newptr;
 390 
 391         for (ptr = TWG(process); ptr < (TWG(process) + TWG(process_size)); ptr++) {
 392                 if (ptr->stream == stream) {
 393                         break;
 394                 }
 395         }
 396 
 397         if (ptr < (TWG(process) + TWG(process_size))) {
 398                 return ptr;
 399         }
 400 
 401         newptr = (process_pair*)realloc((void*)TWG(process), (TWG(process_size)+1)*sizeof(process_pair));
 402         if (newptr == NULL) {
 403                 return NULL;
 404         }
 405 
 406         TWG(process) = newptr;
 407         ptr = newptr + TWG(process_size);
 408         TWG(process_size)++;
 409         return ptr;
 410 }
 411 
 412 static shm_pair *shm_get(int key, void *addr)
 413 {
 414         shm_pair *ptr;
 415         shm_pair *newptr;
 416 
 417         for (ptr = TWG(shm); ptr < (TWG(shm) + TWG(shm_size)); ptr++) {
 418                 if (!ptr->descriptor) {
 419                         continue;
 420                 }
 421                 if (!addr && ptr->descriptor->shm_perm.key == key) {
 422                         break;
 423                 } else if (ptr->addr == addr) {
 424                         break;
 425                 }
 426         }
 427 
 428         if (ptr < (TWG(shm) + TWG(shm_size))) {
 429                 return ptr;
 430         }
 431 
 432         newptr = (shm_pair*)realloc((void*)TWG(shm), (TWG(shm_size)+1)*sizeof(shm_pair));
 433         if (newptr == NULL) {
 434                 return NULL;
 435         }
 436 
 437         TWG(shm) = newptr;
 438         ptr = newptr + TWG(shm_size);
 439         TWG(shm_size)++;
 440         memset(ptr, 0, sizeof(*ptr));
 441         return ptr;
 442 }
 443 
 444 static HANDLE dupHandle(HANDLE fh, BOOL inherit) {
 445         HANDLE copy, self = GetCurrentProcess();
 446         if (!DuplicateHandle(self, fh, self, &copy, 0, inherit, DUPLICATE_SAME_ACCESS|DUPLICATE_CLOSE_SOURCE)) {
 447                 return NULL;
 448         }
 449         return copy;
 450 }
 451 
 452 TSRM_API FILE *popen(const char *command, const char *type)
 453 {
 454 
 455         return popen_ex(command, type, NULL, NULL);
 456 }
 457 
 458 TSRM_API FILE *popen_ex(const char *command, const char *type, const char *cwd, char *env)
 459 {
 460         FILE *stream = NULL;
 461         int fno, type_len, read, mode;
 462         STARTUPINFO startup;
 463         PROCESS_INFORMATION process;
 464         SECURITY_ATTRIBUTES security;
 465         HANDLE in, out;
 466         DWORD dwCreateFlags = 0;
 467         BOOL res;
 468         process_pair *proc;
 469         char *cmd;
 470         int i;
 471         char *ptype = (char *)type;
 472         HANDLE thread_token = NULL;
 473         HANDLE token_user = NULL;
 474         BOOL asuser = TRUE;
 475 
 476         if (!type) {
 477                 return NULL;
 478         }
 479 
 480         /*The following two checks can be removed once we drop XP support */
 481         type_len = (int)strlen(type);
 482         if (type_len <1 || type_len > 2) {
 483                 return NULL;
 484         }
 485 
 486         for (i=0; i < type_len; i++) {
 487                 if (!(*ptype == 'r' || *ptype == 'w' || *ptype == 'b' || *ptype == 't')) {
 488                         return NULL;
 489                 }
 490                 ptype++;
 491         }
 492 
 493         security.nLength                                = sizeof(SECURITY_ATTRIBUTES);
 494         security.bInheritHandle                 = TRUE;
 495         security.lpSecurityDescriptor   = NULL;
 496 
 497         if (!type_len || !CreatePipe(&in, &out, &security, 2048L)) {
 498                 return NULL;
 499         }
 500 
 501         memset(&startup, 0, sizeof(STARTUPINFO));
 502         memset(&process, 0, sizeof(PROCESS_INFORMATION));
 503 
 504         startup.cb                      = sizeof(STARTUPINFO);
 505         startup.dwFlags         = STARTF_USESTDHANDLES;
 506         startup.hStdError       = GetStdHandle(STD_ERROR_HANDLE);
 507 
 508         read = (type[0] == 'r') ? TRUE : FALSE;
 509         mode = ((type_len == 2) && (type[1] == 'b')) ? O_BINARY : O_TEXT;
 510 
 511         if (read) {
 512                 in = dupHandle(in, FALSE);
 513                 startup.hStdInput  = GetStdHandle(STD_INPUT_HANDLE);
 514                 startup.hStdOutput = out;
 515         } else {
 516                 out = dupHandle(out, FALSE);
 517                 startup.hStdInput  = in;
 518                 startup.hStdOutput = GetStdHandle(STD_OUTPUT_HANDLE);
 519         }
 520 
 521         dwCreateFlags = NORMAL_PRIORITY_CLASS;
 522         if (strcmp(sapi_module.name, "cli") != 0) {
 523                 dwCreateFlags |= CREATE_NO_WINDOW;
 524         }
 525 
 526         /* Get a token with the impersonated user. */
 527         if(OpenThreadToken(GetCurrentThread(), TOKEN_ALL_ACCESS, TRUE, &thread_token)) {
 528                 DuplicateTokenEx(thread_token, MAXIMUM_ALLOWED, &security, SecurityImpersonation, TokenPrimary, &token_user);
 529         } else {
 530                 DWORD err = GetLastError();
 531                 if (err == ERROR_NO_TOKEN) {
 532                         asuser = FALSE;
 533                 }
 534         }
 535 
 536         cmd = (char*)malloc(strlen(command)+strlen(TWG(comspec))+sizeof(" /c ")+2);
 537         if (!cmd) {
 538                 return NULL;
 539         }
 540 
 541         sprintf(cmd, "%s /c \"%s\"", TWG(comspec), command);
 542         if (asuser) {
 543                 res = CreateProcessAsUser(token_user, NULL, cmd, &security, &security, security.bInheritHandle, dwCreateFlags, env, cwd, &startup, &process);
 544                 CloseHandle(token_user);
 545         } else {
 546                 res = CreateProcess(NULL, cmd, &security, &security, security.bInheritHandle, dwCreateFlags, env, cwd, &startup, &process);
 547         }
 548         free(cmd);
 549 
 550         if (!res) {
 551                 return NULL;
 552         }
 553 
 554         CloseHandle(process.hThread);
 555         proc = process_get(NULL);
 556 
 557         if (read) {
 558                 fno = _open_osfhandle((tsrm_intptr_t)in, _O_RDONLY | mode);
 559                 CloseHandle(out);
 560         } else {
 561                 fno = _open_osfhandle((tsrm_intptr_t)out, _O_WRONLY | mode);
 562                 CloseHandle(in);
 563         }
 564 
 565         stream = _fdopen(fno, type);
 566         proc->prochnd = process.hProcess;
 567         proc->stream = stream;
 568         return stream;
 569 }
 570 
 571 TSRM_API int pclose(FILE *stream)
 572 {
 573         DWORD termstat = 0;
 574         process_pair *process;
 575 
 576         if ((process = process_get(stream)) == NULL) {
 577                 return 0;
 578         }
 579 
 580         fflush(process->stream);
 581         fclose(process->stream);
 582 
 583         WaitForSingleObject(process->prochnd, INFINITE);
 584         GetExitCodeProcess(process->prochnd, &termstat);
 585         process->stream = NULL;
 586         CloseHandle(process->prochnd);
 587 
 588         return termstat;
 589 }
 590 
 591 TSRM_API int shmget(int key, int size, int flags)
 592 {
 593         shm_pair *shm;
 594         char shm_segment[26], shm_info[29];
 595         HANDLE shm_handle, info_handle;
 596         BOOL created = FALSE;
 597 
 598         if (size < 0) {
 599                 return -1;
 600         }
 601 
 602         snprintf(shm_segment, sizeof(shm_segment), "TSRM_SHM_SEGMENT:%d", key);
 603         snprintf(shm_info, sizeof(shm_info), "TSRM_SHM_DESCRIPTOR:%d", key);
 604 
 605         shm_handle  = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_segment);
 606         info_handle = OpenFileMapping(FILE_MAP_ALL_ACCESS, FALSE, shm_info);
 607 
 608         if (!shm_handle && !info_handle) {
 609                 if (flags & IPC_CREAT) {
 610                         shm_handle      = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, size, shm_segment);
 611                         info_handle     = CreateFileMapping(INVALID_HANDLE_VALUE, NULL, PAGE_READWRITE, 0, sizeof(shm->descriptor), shm_info);
 612                         created         = TRUE;
 613                 }
 614                 if (!shm_handle || !info_handle) {
 615                         if (shm_handle) {
 616                                 CloseHandle(shm_handle);
 617                         }
 618                         if (info_handle) {
 619                                 CloseHandle(info_handle);
 620                         }
 621                         return -1;
 622                 }
 623         } else {
 624                 if (flags & IPC_EXCL) {
 625                         return -1;
 626                 }
 627         }
 628 
 629         shm = shm_get(key, NULL);
 630         if (!shm) {
 631                 CloseHandle(shm_handle);
 632                 CloseHandle(info_handle);
 633                 return -1;
 634         }
 635         shm->segment = shm_handle;
 636         shm->info        = info_handle;
 637         shm->descriptor = MapViewOfFileEx(shm->info, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
 638 
 639         if (NULL != shm->descriptor && created) {
 640                 shm->descriptor->shm_perm.key   = key;
 641                 shm->descriptor->shm_segsz              = size;
 642                 shm->descriptor->shm_ctime              = time(NULL);
 643                 shm->descriptor->shm_cpid               = getpid();
 644                 shm->descriptor->shm_perm.mode  = flags;
 645 
 646                 shm->descriptor->shm_perm.cuid  = shm->descriptor->shm_perm.cgid= 0;
 647                 shm->descriptor->shm_perm.gid   = shm->descriptor->shm_perm.uid = 0;
 648                 shm->descriptor->shm_atime              = shm->descriptor->shm_dtime    = 0;
 649                 shm->descriptor->shm_lpid               = shm->descriptor->shm_nattch   = 0;
 650                 shm->descriptor->shm_perm.mode  = shm->descriptor->shm_perm.seq = 0;
 651         }
 652 
 653         if (NULL != shm->descriptor && (shm->descriptor->shm_perm.key != key || size > shm->descriptor->shm_segsz)) {
 654                 if (NULL != shm->segment) {
 655                         CloseHandle(shm->segment);
 656                 }
 657                 UnmapViewOfFile(shm->descriptor);
 658                 CloseHandle(shm->info);
 659                 return -1;
 660         }
 661 
 662         return key;
 663 }
 664 
 665 TSRM_API void *shmat(int key, const void *shmaddr, int flags)
 666 {
 667         shm_pair *shm = shm_get(key, NULL);
 668 
 669         if (!shm->segment) {
 670                 return (void*)-1;
 671         }
 672 
 673         shm->descriptor->shm_atime = time(NULL);
 674         shm->descriptor->shm_lpid  = getpid();
 675         shm->descriptor->shm_nattch++;
 676 
 677         shm->addr = MapViewOfFileEx(shm->segment, FILE_MAP_ALL_ACCESS, 0, 0, 0, NULL);
 678 
 679         return shm->addr;
 680 }
 681 
 682 TSRM_API int shmdt(const void *shmaddr)
 683 {
 684         shm_pair *shm = shm_get(0, (void*)shmaddr);
 685 
 686         if (!shm->segment) {
 687                 return -1;
 688         }
 689 
 690         shm->descriptor->shm_dtime = time(NULL);
 691         shm->descriptor->shm_lpid  = getpid();
 692         shm->descriptor->shm_nattch--;
 693 
 694         return UnmapViewOfFile(shm->addr) ? 0 : -1;
 695 }
 696 
 697 TSRM_API int shmctl(int key, int cmd, struct shmid_ds *buf) {
 698         shm_pair *shm = shm_get(key, NULL);
 699 
 700         if (!shm->segment) {
 701                 return -1;
 702         }
 703 
 704         switch (cmd) {
 705                 case IPC_STAT:
 706                         memcpy(buf, shm->descriptor, sizeof(struct shmid_ds));
 707                         return 0;
 708 
 709                 case IPC_SET:
 710                         shm->descriptor->shm_ctime              = time(NULL);
 711                         shm->descriptor->shm_perm.uid   = buf->shm_perm.uid;
 712                         shm->descriptor->shm_perm.gid   = buf->shm_perm.gid;
 713                         shm->descriptor->shm_perm.mode  = buf->shm_perm.mode;
 714                         return 0;
 715 
 716                 case IPC_RMID:
 717                         if (shm->descriptor->shm_nattch < 1) {
 718                                 shm->descriptor->shm_perm.key = -1;
 719                         }
 720                         return 0;
 721 
 722                 default:
 723                         return -1;
 724         }
 725 }
 726 
 727 TSRM_API char *realpath(char *orig_path, char *buffer)
 728 {
 729         int ret = GetFullPathName(orig_path, _MAX_PATH, buffer, NULL);
 730         if(!ret || ret > _MAX_PATH) {
 731                 return NULL;
 732         }
 733         return buffer;
 734 }
 735 
 736 #if HAVE_UTIME
 737 static zend_always_inline void UnixTimeToFileTime(time_t t, LPFILETIME pft) /* {{{ */
 738 {
 739         // Note that LONGLONG is a 64-bit value
 740         LONGLONG ll;
 741 
 742         ll = Int32x32To64(t, 10000000) + 116444736000000000;
 743         pft->dwLowDateTime = (DWORD)ll;
 744         pft->dwHighDateTime = ll >> 32;
 745 }
 746 /* }}} */
 747 
 748 TSRM_API int win32_utime(const char *filename, struct utimbuf *buf) /* {{{ */
 749 {
 750         FILETIME mtime, atime;
 751         HANDLE hFile;
 752 
 753         hFile = CreateFile(filename, GENERIC_WRITE, FILE_SHARE_WRITE|FILE_SHARE_READ, NULL,
 754                                  OPEN_ALWAYS, FILE_FLAG_BACKUP_SEMANTICS, NULL);
 755 
 756         /* OPEN_ALWAYS mode sets the last error to ERROR_ALREADY_EXISTS but
 757            the CreateFile operation succeeds */
 758         if (GetLastError() == ERROR_ALREADY_EXISTS) {
 759                 SetLastError(0);
 760         }
 761 
 762         if ( hFile == INVALID_HANDLE_VALUE ) {
 763                 return -1;
 764         }
 765 
 766         if (!buf) {
 767                 SYSTEMTIME st;
 768                 GetSystemTime(&st);
 769                 SystemTimeToFileTime(&st, &mtime);
 770                 atime = mtime;
 771         } else {
 772                 UnixTimeToFileTime(buf->modtime, &mtime);
 773                 UnixTimeToFileTime(buf->actime, &atime);
 774         }
 775         if (!SetFileTime(hFile, NULL, &atime, &mtime)) {
 776                 CloseHandle(hFile);
 777                 return -1;
 778         }
 779         CloseHandle(hFile);
 780         return 1;
 781 }
 782 /* }}} */
 783 #endif
 784 #endif

/* [<][>][^][v][top][bottom][index][help] */