📄 os_win32.c
字号:
if(hStdinCompPort == INVALID_HANDLE_VALUE) { printf("<H2>OS_LibInit Failed CreateIoCompletionPort: STDIN! ERROR: %d</H2>\r\n\r\n", GetLastError()); return -1; } } /* * Create the thread that will read stdin if the CONTENT_LENGTH * is non-zero. */ if((cLenPtr = getenv("CONTENT_LENGTH")) != NULL && atoi(cLenPtr) > 0) { hStdinThread = (HANDLE) _beginthread(StdinThread, 0, NULL); if (hStdinThread == (HANDLE) -1) { printf("<H2>OS_LibInit Failed to create STDIN thread! ERROR: %d</H2>\r\n\r\n", GetLastError()); return -1; } } /* * STDOUT will be used synchronously. * * XXX: May want to convert this so that it could be used for OVERLAPPED * I/O later. If so, model it after the Stdin I/O as stdout is * also incapable of async I/O on some servers. */ stdioHandles[STDOUT_FILENO] = GetStdHandle(STD_OUTPUT_HANDLE); if(!SetHandleInformation(stdioHandles[STDOUT_FILENO], HANDLE_FLAG_INHERIT, FALSE)) { //exit(99); return -1; } if ((fakeFd = Win32NewDescriptor(FD_PIPE_SYNC, (int)stdioHandles[STDOUT_FILENO], STDOUT_FILENO)) == -1) { return -1; } else { /* * Set stdout equal to our pseudo FD */ stdioFds[STDOUT_FILENO] = fakeFd; } stdioHandles[STDERR_FILENO] = GetStdHandle(STD_ERROR_HANDLE); if(!SetHandleInformation(stdioHandles[STDERR_FILENO], HANDLE_FLAG_INHERIT, FALSE)) { //exit(99); return -1; } if ((fakeFd = Win32NewDescriptor(FD_PIPE_SYNC, (int)stdioHandles[STDERR_FILENO], STDERR_FILENO)) == -1) { return -1; } else { /* * Set stderr equal to our pseudo FD */ stdioFds[STDERR_FILENO] = fakeFd; } return 0;}/* *-------------------------------------------------------------- * * OS_LibShutdown -- * * Shutdown the OS library. * * Results: * None. * * Side effects: * Memory freed, handles closed. * *-------------------------------------------------------------- */void OS_LibShutdown(){ if (hIoCompPort != INVALID_HANDLE_VALUE) { CloseHandle(hIoCompPort); hIoCompPort = INVALID_HANDLE_VALUE; } if (hStdinCompPort != INVALID_HANDLE_VALUE) { CloseHandle(hStdinCompPort); hStdinCompPort = INVALID_HANDLE_VALUE; } if (acceptMutex != INVALID_HANDLE_VALUE) { ReleaseMutex(acceptMutex); } /* we only want to do this if we're not a web server */ if (stdioHandles[0] != INVALID_HANDLE_VALUE) { DisconnectNamedPipe(hListen); CancelIo(hListen); OS_StopImpersonation(); } WSACleanup();}/* *-------------------------------------------------------------- * * Win32FreeDescriptor -- * * Free I/O descriptor entry in fdTable. * * Results: * Frees I/O descriptor entry in fdTable. * * Side effects: * None. * *-------------------------------------------------------------- */static void Win32FreeDescriptor(int fd){ /* Catch it if fd is a bogus value */ ASSERT((fd >= 0) && (fd < WIN32_OPEN_MAX)); EnterCriticalSection(&fdTableCritical); if (fdTable[fd].type != FD_UNUSED) { switch (fdTable[fd].type) { case FD_FILE_SYNC: case FD_FILE_ASYNC: /* Free file path string */ ASSERT(fdTable[fd].path != NULL); free(fdTable[fd].path); fdTable[fd].path = NULL; break; default: break; } ASSERT(fdTable[fd].path == NULL); fdTable[fd].type = FD_UNUSED; fdTable[fd].path = NULL; fdTable[fd].Errno = NO_ERROR; fdTable[fd].offsetHighPtr = fdTable[fd].offsetLowPtr = NULL; if (fdTable[fd].hMapMutex != NULL) { CloseHandle(fdTable[fd].hMapMutex); fdTable[fd].hMapMutex = NULL; } } LeaveCriticalSection(&fdTableCritical); return;}static short getPort(const char * bindPath){ short port = 0; char * p = strchr(bindPath, ':'); if (p && *++p) { char buf[6]; strncpy(buf, p, 6); buf[5] = '\0'; port = (short) atoi(buf); } return port;}/**This function builds a Dacl which grants the creator of the objectsFILE_ALL_ACCESS and Everyone FILE_GENERIC_READ and FILE_GENERIC_WRITEaccess to the object.This Dacl allows for higher security than a NULL Dacl, which is common fornamed-pipes, as this only grants the creator/owner write access to thesecurity descriptor, and grants Everyone the ability to "use" the named-pipe.This scenario prevents a malevolent user from disrupting service by preventingarbitrary access manipulation.**/BOOLBuildNamedPipeAcl( PACL pAcl, PDWORD cbAclSize ){ DWORD dwAclSize; SID_IDENTIFIER_AUTHORITY siaWorld = SECURITY_WORLD_SID_AUTHORITY; SID_IDENTIFIER_AUTHORITY siaCreator = SECURITY_CREATOR_SID_AUTHORITY; BYTE BufEveryoneSid[32]; BYTE BufOwnerSid[32]; PSID pEveryoneSid = (PSID)BufEveryoneSid; PSID pOwnerSid = (PSID)BufOwnerSid; // // compute size of acl // dwAclSize = sizeof(ACL) + 2 * ( sizeof(ACCESS_ALLOWED_ACE) - sizeof(DWORD) ) + GetSidLengthRequired( 1 ) + // well-known Everyone Sid GetSidLengthRequired( 1 ) ; // well-known Creator Owner Sid if(*cbAclSize < dwAclSize) { *cbAclSize = dwAclSize; return FALSE; } *cbAclSize = dwAclSize; // // intialize well known sids // if(!InitializeSid(pEveryoneSid, &siaWorld, 1)) return FALSE; *GetSidSubAuthority(pEveryoneSid, 0) = SECURITY_WORLD_RID; if(!InitializeSid(pOwnerSid, &siaCreator, 1)) return FALSE; *GetSidSubAuthority(pOwnerSid, 0) = SECURITY_CREATOR_OWNER_RID; if(!InitializeAcl(pAcl, dwAclSize, ACL_REVISION)) return FALSE; // // if(!AddAccessAllowedAce( pAcl, ACL_REVISION, FILE_GENERIC_READ | FILE_GENERIC_WRITE, pEveryoneSid )) return FALSE; // // return AddAccessAllowedAce( pAcl, ACL_REVISION, FILE_ALL_ACCESS, pOwnerSid );}/* * OS_CreateLocalIpcFd -- * * This procedure is responsible for creating the listener pipe * on Windows NT for local process communication. It will create a * named pipe and return a file descriptor to it to the caller. * * Results: * Listener pipe created. This call returns either a valid * pseudo file descriptor or -1 on error. * * Side effects: * Listener pipe and IPC address are stored in the FCGI info * structure. * 'errno' will set on errors (-1 is returned). * *---------------------------------------------------------------------- */int OS_CreateLocalIpcFd(const char *bindPath, int backlog){ int pseudoFd = -1; short port = getPort(bindPath); if (acceptMutex == INVALID_HANDLE_VALUE) { acceptMutex = CreateMutex(NULL, FALSE, NULL); if (acceptMutex == NULL) return -2; if (! SetHandleInformation(acceptMutex, HANDLE_FLAG_INHERIT, TRUE)) return -3; } // There's nothing to be gained (at the moment) by a shutdown Event if (port && *bindPath != ':' && strncmp(bindPath, LOCALHOST, strlen(LOCALHOST))) { fprintf(stderr, "To start a service on a TCP port can not " "specify a host name.\n" "You should either use \"localhost:<port>\" or " " just use \":<port>.\"\n"); //exit(1); return -1; } listenType = (port) ? FD_SOCKET_SYNC : FD_PIPE_ASYNC; if (port) { SOCKET listenSock; struct sockaddr_in sockAddr; int sockLen = sizeof(sockAddr); memset(&sockAddr, 0, sizeof(sockAddr)); sockAddr.sin_family = AF_INET; sockAddr.sin_addr.s_addr = htonl(INADDR_ANY); sockAddr.sin_port = htons(port); listenSock = socket(AF_INET, SOCK_STREAM, 0); if (listenSock == INVALID_SOCKET) { return -4; } if (bind(listenSock, (struct sockaddr *) &sockAddr, sockLen) ) { return -12; } if (listen(listenSock, backlog)) { return -5; } pseudoFd = Win32NewDescriptor(listenType, listenSock, -1); if (pseudoFd == -1) { closesocket(listenSock); return -6; } hListen = (HANDLE) listenSock; } else { SECURITY_ATTRIBUTES sa; SECURITY_DESCRIPTOR sd; BYTE AclBuf[ 64 ]; DWORD cbAclSize = 64; PACL pAcl = (PACL)AclBuf; HANDLE hListenPipe = INVALID_HANDLE_VALUE; char *pipePath = malloc(strlen(bindPathPrefix) + strlen(bindPath) + 1); if (! pipePath) { return -7; } strcpy(pipePath, bindPathPrefix); strcat(pipePath, bindPath); if (bImpersonate) { // get the security attributes for Everybody to connect // we do this so that multithreaded servers that run // threads under secured users can access pipes created // by a system level thread (for instance, IIS) // // suppress errors regarding startup directory, etc // SetErrorMode(SEM_FAILCRITICALERRORS); if(!BuildNamedPipeAcl(pAcl, &cbAclSize)) { fprintf(stderr, "BuildNamedPipeAcl"); return -100; } if(!InitializeSecurityDescriptor(&sd, SECURITY_DESCRIPTOR_REVISION)) { fprintf(stderr, "InitializeSecurityDescriptor"); return -100; } if(!SetSecurityDescriptorDacl(&sd, TRUE, pAcl, FALSE)) { fprintf(stderr, "SetSecurityDescriptorDacl"); return -100; } sa.nLength = sizeof(SECURITY_ATTRIBUTES); sa.lpSecurityDescriptor = &sd; // default Dacl of caller sa.bInheritHandle = TRUE; } hListenPipe = CreateNamedPipe(pipePath, PIPE_ACCESS_DUPLEX, PIPE_TYPE_BYTE | PIPE_WAIT | PIPE_READMODE_BYTE, PIPE_UNLIMITED_INSTANCES, 4096, 4096, 0, bImpersonate?&sa:NULL); free(pipePath); if (hListenPipe == INVALID_HANDLE_VALUE) { return -8; } if (! SetHandleInformation(hListenPipe, HANDLE_FLAG_INHERIT, TRUE)) { return -9; } pseudoFd = Win32NewDescriptor(listenType, (int) hListenPipe, -1); if (pseudoFd == -1) { CloseHandle(hListenPipe); return -10; } hListen = (HANDLE) hListenPipe; } return pseudoFd;}/* *---------------------------------------------------------------------- * * OS_FcgiConnect -- * * Create the pipe pathname connect to the remote application if * possible. * * Results: * -1 if fail or a valid handle if connection succeeds. * * Side effects: * Remote connection established. * *---------------------------------------------------------------------- */int OS_FcgiConnect(char *bindPath){ short port = getPort(bindPath); int pseudoFd = -1; unsigned int flags = FILE_FLAG_OVERLAPPED; if (port) { struct hostent *hp; char *host = NULL; struct sockaddr_in sockAddr; int sockLen = sizeof(sockAddr); SOCKET sock; if (*bindPath != ':') { char * p = strchr(bindPath, ':'); if (p) { int len = p - bindPath + 1; host = (char *)malloc(len); if (!host) { fprintf(stderr, "Unable to allocate memory\n"); return -1; } strncpy(host, bindPath, len); host[len-1] = '\0'; } } hp = gethostbyname(host ? host : LOCALHOST); if (host) { free(host); } if (hp == NULL) { fprintf(stderr, "Unknown host: %s\n", bindPath); return -1; } memset(&sockAddr, 0, sizeof(sockAddr)); sockAddr.sin_family = AF_INET; memcpy(&sockAddr.sin_addr, hp->h_addr, hp->h_length); sockAddr.sin_port = htons(port); sock = socket(AF_INET, SOCK_STREAM, 0); if (sock == INVALID_SOCKET) { return -1; } if (connect(sock, (struct sockaddr *) &sockAddr, sockLen) == SOCKET_ERROR) { closesocket(sock); return -1; } pseudoFd = Win32NewDescriptor(FD_SOCKET_SYNC, sock, -1); if (pseudoFd == -1) { closesocket(sock); return -1; } } else { char *pipePath = malloc(strlen(bindPathPrefix) + strlen(bindPath) + 1); HANDLE hPipe; if (! pipePath) { return -1;
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -