1/* Licensed to the Apache Software Foundation (ASF) under one or more 2 * contributor license agreements. See the NOTICE file distributed with 3 * this work for additional information regarding copyright ownership. 4 * The ASF licenses this file to You under the Apache License, Version 2.0 5 * (the "License"); you may not use this file except in compliance with 6 * the License. You may obtain a copy of the License at 7 * 8 * http://www.apache.org/licenses/LICENSE-2.0 9 * 10 * Unless required by applicable law or agreed to in writing, software 11 * distributed under the License is distributed on an "AS IS" BASIS, 12 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 * See the License for the specific language governing permissions and 14 * limitations under the License. 15 */ 16 17#include "apr_private.h" 18#include "apr_general.h" 19#include "apr_pools.h" 20#include "apr_signal.h" 21#include "shellapi.h" 22 23#include "apr_arch_misc.h" /* for WSAHighByte / WSALowByte */ 24#include "wchar.h" 25#include "apr_arch_file_io.h" /* bring in unicode-ness */ 26#include "apr_arch_threadproc.h" /* bring in apr_threadproc_init */ 27#include "assert.h" 28 29/* This symbol is _private_, although it must be exported. 30 */ 31int APR_DECLARE_DATA apr_app_init_complete = 0; 32 33#if !defined(_WIN32_WCE) 34/* Used by apr_app_initialize to reprocess the environment 35 * 36 * An internal apr function to convert a double-null terminated set 37 * of single-null terminated strings from wide Unicode to narrow utf-8 38 * as a list of strings. These are allocated from the MSVCRT's 39 * _CRT_BLOCK to trick the system into trusting our store. 40 */ 41static int warrsztoastr(const char * const * *retarr, 42 const wchar_t * arrsz, int args) 43{ 44 const apr_wchar_t *wch; 45 apr_size_t totlen; 46 apr_size_t newlen; 47 apr_size_t wsize; 48 char **env; 49 char *pstrs; 50 char *strs; 51 int arg; 52 53 if (args < 0) { 54 for (args = 1, wch = arrsz; wch[0] || wch[1]; ++wch) 55 if (!*wch) 56 ++args; 57 } 58 wsize = 1 + wch - arrsz; 59 60 /* This is a safe max allocation, we will alloc each 61 * string exactly after processing and return this 62 * temporary buffer to the free store. 63 * 3 ucs bytes hold any single wchar_t value (16 bits) 64 * 4 ucs bytes will hold a wchar_t pair value (20 bits) 65 */ 66 newlen = totlen = wsize * 3 + 1; 67 pstrs = strs = apr_malloc_dbg(newlen * sizeof(char), 68 __FILE__, __LINE__); 69 70 (void)apr_conv_ucs2_to_utf8(arrsz, &wsize, strs, &newlen); 71 72 assert(newlen && !wsize); 73 74 *retarr = env = apr_malloc_dbg((args + 1) * sizeof(char*), 75 __FILE__, __LINE__); 76 for (arg = 0; arg < args; ++arg) { 77 char* p = pstrs; 78 int len = 0; 79 while (*p++) 80 ++len; 81 len += 1; 82 83 *env = apr_malloc_dbg(len * sizeof(char), 84 __FILE__, __LINE__); 85 memcpy(*env, pstrs, len * sizeof(char)); 86 87 pstrs += len; 88 ++env; 89 } 90 91 *env = NULL; 92 free(strs); 93 94 return args; 95} 96#endif 97 98/* Reprocess the arguments to main() for a completely apr-ized application 99 */ 100 101APR_DECLARE(apr_status_t) apr_app_initialize(int *argc, 102 const char * const * *argv, 103 const char * const * *env) 104{ 105 apr_status_t rv = apr_initialize(); 106 107 if (rv != APR_SUCCESS) { 108 return rv; 109 } 110 111#if defined(_WIN32_WCE) 112 apr_app_init_complete = 1; 113#elif APR_HAS_UNICODE_FS 114 IF_WIN_OS_IS_UNICODE 115 { 116 apr_wchar_t **wstrs; 117 apr_wchar_t *sysstr; 118 int wstrc; 119 int dupenv; 120 121 if (apr_app_init_complete) { 122 return rv; 123 } 124 125 apr_app_init_complete = 1; 126 127 sysstr = GetCommandLineW(); 128 if (sysstr) { 129 wstrs = CommandLineToArgvW(sysstr, &wstrc); 130 if (wstrs) { 131 *argc = apr_wastrtoastr(argv, wstrs, wstrc); 132 GlobalFree(wstrs); 133 } 134 } 135 136 sysstr = GetEnvironmentStringsW(); 137 dupenv = warrsztoastr(&_environ, sysstr, -1); 138 139 if (env) { 140 *env = apr_malloc_dbg((dupenv + 1) * sizeof (char *), 141 __FILE__, __LINE__ ); 142 memcpy((void*)*env, _environ, (dupenv + 1) * sizeof (char *)); 143 } 144 else { 145 } 146 147 FreeEnvironmentStringsW(sysstr); 148 149 /* MSVCRT will attempt to maintain the wide environment calls 150 * on _putenv(), which is bogus if we've passed a non-ascii 151 * string to _putenv(), since they use MultiByteToWideChar 152 * and breaking the implicit utf-8 assumption we've built. 153 * 154 * Reset _wenviron for good measure. 155 */ 156 if (_wenviron) { 157 apr_wchar_t **wenv = _wenviron; 158 _wenviron = NULL; 159 free(wenv); 160 } 161 162 } 163#endif 164 return rv; 165} 166 167static int initialized = 0; 168 169/* Provide to win32/thread.c */ 170extern DWORD tls_apr_thread; 171 172APR_DECLARE(apr_status_t) apr_initialize(void) 173{ 174 apr_pool_t *pool; 175 apr_status_t status; 176 int iVersionRequested; 177 WSADATA wsaData; 178 int err; 179 apr_oslevel_e osver; 180 181 if (initialized++) { 182 return APR_SUCCESS; 183 } 184 185 /* Initialize apr_os_level global */ 186 if (apr_get_oslevel(&osver) != APR_SUCCESS) { 187 return APR_EEXIST; 188 } 189 190 tls_apr_thread = TlsAlloc(); 191 if ((status = apr_pool_initialize()) != APR_SUCCESS) 192 return status; 193 194 if (apr_pool_create(&pool, NULL) != APR_SUCCESS) { 195 return APR_ENOPOOL; 196 } 197 198 apr_pool_tag(pool, "apr_initialize"); 199 200 iVersionRequested = MAKEWORD(WSAHighByte, WSALowByte); 201 err = WSAStartup((WORD) iVersionRequested, &wsaData); 202 if (err) { 203 return err; 204 } 205 if (LOBYTE(wsaData.wVersion) != WSAHighByte || 206 HIBYTE(wsaData.wVersion) != WSALowByte) { 207 WSACleanup(); 208 return APR_EEXIST; 209 } 210 211 apr_signal_init(pool); 212 213 apr_threadproc_init(pool); 214 215 return APR_SUCCESS; 216} 217 218APR_DECLARE_NONSTD(void) apr_terminate(void) 219{ 220 initialized--; 221 if (initialized) { 222 return; 223 } 224 apr_pool_terminate(); 225 226 WSACleanup(); 227 228 TlsFree(tls_apr_thread); 229} 230 231APR_DECLARE(void) apr_terminate2(void) 232{ 233 apr_terminate(); 234} 235