224 lines
6.0 KiB
C
224 lines
6.0 KiB
C
/* Licensed to the Apache Software Foundation (ASF) under one or more
|
|
* contributor license agreements. See the NOTICE file distributed with
|
|
* this work for additional information regarding copyright ownership.
|
|
* The ASF licenses this file to You under the Apache License, Version 2.0
|
|
* (the "License"); you may not use this file except in compliance with
|
|
* the License. You may obtain a copy of the License at
|
|
*
|
|
* http://www.apache.org/licenses/LICENSE-2.0
|
|
*
|
|
* Unless required by applicable law or agreed to in writing, software
|
|
* distributed under the License is distributed on an "AS IS" BASIS,
|
|
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
|
|
* See the License for the specific language governing permissions and
|
|
* limitations under the License.
|
|
*/
|
|
|
|
#include "fspr_private.h"
|
|
#include "fspr_general.h"
|
|
#include "fspr_pools.h"
|
|
#include "fspr_signal.h"
|
|
#include "ShellAPI.h"
|
|
|
|
#include "fspr_arch_misc.h" /* for WSAHighByte / WSALowByte */
|
|
#include "wchar.h"
|
|
#include "fspr_arch_file_io.h"
|
|
#include "crtdbg.h"
|
|
#include "assert.h"
|
|
|
|
/* This symbol is _private_, although it must be exported.
|
|
*/
|
|
int APR_DECLARE_DATA fspr_app_init_complete = 0;
|
|
|
|
/* Used by fspr_app_initialize to reprocess the environment
|
|
*
|
|
* An internal apr function to convert a double-null terminated set
|
|
* of single-null terminated strings from wide Unicode to narrow utf-8
|
|
* as a list of strings. These are allocated from the MSVCRT's
|
|
* _CRT_BLOCK to trick the system into trusting our store.
|
|
*/
|
|
static int warrsztoastr(const char * const * *retarr,
|
|
const wchar_t * arrsz, int args)
|
|
{
|
|
const fspr_wchar_t *wch;
|
|
fspr_size_t totlen;
|
|
fspr_size_t newlen;
|
|
fspr_size_t wsize;
|
|
char **newarr;
|
|
int arg;
|
|
|
|
if (args < 0) {
|
|
for (args = 1, wch = arrsz; wch[0] || wch[1]; ++wch)
|
|
if (!*wch)
|
|
++args;
|
|
}
|
|
wsize = 1 + wch - arrsz;
|
|
|
|
newarr = _malloc_dbg((args + 1) * sizeof(char *),
|
|
_CRT_BLOCK, __FILE__, __LINE__);
|
|
|
|
/* This is a safe max allocation, we will realloc after
|
|
* processing and return the excess to the free store.
|
|
* 3 ucs bytes hold any single wchar_t value (16 bits)
|
|
* 4 ucs bytes will hold a wchar_t pair value (20 bits)
|
|
*/
|
|
newlen = totlen = wsize * 3 + 1;
|
|
newarr[0] = _malloc_dbg(newlen * sizeof(char),
|
|
_CRT_BLOCK, __FILE__, __LINE__);
|
|
|
|
(void)fspr_conv_ucs2_to_utf8(arrsz, &wsize,
|
|
newarr[0], &newlen);
|
|
|
|
assert(newlen && !wsize);
|
|
/* Return to the free store if the heap realloc is the least bit optimized
|
|
*/
|
|
newarr[0] = _realloc_dbg(newarr[0], totlen - newlen,
|
|
_CRT_BLOCK, __FILE__, __LINE__);
|
|
|
|
for (arg = 1; arg < args; ++arg) {
|
|
newarr[arg] = newarr[arg - 1] + 2;
|
|
while (*(newarr[arg]++)) {
|
|
/* continue */;
|
|
}
|
|
}
|
|
|
|
newarr[arg] = NULL;
|
|
|
|
*retarr = newarr;
|
|
return args;
|
|
}
|
|
|
|
/* Reprocess the arguments to main() for a completely apr-ized application
|
|
*/
|
|
|
|
APR_DECLARE(fspr_status_t) fspr_app_initialize(int *argc,
|
|
const char * const * *argv,
|
|
const char * const * *env)
|
|
{
|
|
fspr_status_t rv = fspr_initialize();
|
|
|
|
if (rv != APR_SUCCESS) {
|
|
return rv;
|
|
}
|
|
|
|
#if APR_HAS_UNICODE_FS
|
|
IF_WIN_OS_IS_UNICODE
|
|
{
|
|
fspr_wchar_t **wstrs;
|
|
fspr_wchar_t *sysstr;
|
|
int wstrc;
|
|
int dupenv;
|
|
|
|
if (fspr_app_init_complete) {
|
|
return rv;
|
|
}
|
|
|
|
fspr_app_init_complete = 1;
|
|
|
|
sysstr = GetCommandLineW();
|
|
if (sysstr) {
|
|
wstrs = CommandLineToArgvW(sysstr, &wstrc);
|
|
if (wstrs) {
|
|
*argc = fspr_wastrtoastr(argv, wstrs, wstrc);
|
|
GlobalFree(wstrs);
|
|
}
|
|
}
|
|
|
|
sysstr = GetEnvironmentStringsW();
|
|
dupenv = warrsztoastr(&_environ, sysstr, -1);
|
|
|
|
if (env) {
|
|
*env = _malloc_dbg((dupenv + 1) * sizeof (char *),
|
|
_CRT_BLOCK, __FILE__, __LINE__ );
|
|
memcpy((void*)*env, _environ, (dupenv + 1) * sizeof (char *));
|
|
}
|
|
else {
|
|
}
|
|
|
|
FreeEnvironmentStringsW(sysstr);
|
|
|
|
/* MSVCRT will attempt to maintain the wide environment calls
|
|
* on _putenv(), which is bogus if we've passed a non-ascii
|
|
* string to _putenv(), since they use MultiByteToWideChar
|
|
* and breaking the implicit utf-8 assumption we've built.
|
|
*
|
|
* Reset _wenviron for good measure.
|
|
*/
|
|
if (_wenviron) {
|
|
fspr_wchar_t **wenv = _wenviron;
|
|
_wenviron = NULL;
|
|
free(wenv);
|
|
}
|
|
|
|
}
|
|
#endif
|
|
return rv;
|
|
}
|
|
|
|
static int initialized = 0;
|
|
|
|
/* Provide to win32/thread.c */
|
|
extern DWORD tls_fspr_thread;
|
|
|
|
APR_DECLARE(fspr_status_t) fspr_initialize(void)
|
|
{
|
|
fspr_pool_t *pool;
|
|
fspr_status_t status;
|
|
int iVersionRequested;
|
|
WSADATA wsaData;
|
|
int err;
|
|
fspr_oslevel_e osver;
|
|
|
|
if (initialized++) {
|
|
return APR_SUCCESS;
|
|
}
|
|
|
|
/* Initialize fspr_os_level global */
|
|
if (fspr_get_oslevel(&osver) != APR_SUCCESS) {
|
|
return APR_EEXIST;
|
|
}
|
|
|
|
tls_fspr_thread = TlsAlloc();
|
|
if ((status = fspr_pool_initialize()) != APR_SUCCESS)
|
|
return status;
|
|
|
|
if (fspr_pool_create(&pool, NULL) != APR_SUCCESS) {
|
|
return APR_ENOPOOL;
|
|
}
|
|
|
|
fspr_pool_tag(pool, "fspr_initialize");
|
|
|
|
iVersionRequested = MAKEWORD(WSAHighByte, WSALowByte);
|
|
err = WSAStartup((WORD) iVersionRequested, &wsaData);
|
|
if (err) {
|
|
return err;
|
|
}
|
|
if (LOBYTE(wsaData.wVersion) != WSAHighByte ||
|
|
HIBYTE(wsaData.wVersion) != WSALowByte) {
|
|
WSACleanup();
|
|
return APR_EEXIST;
|
|
}
|
|
|
|
fspr_signal_init(pool);
|
|
|
|
return APR_SUCCESS;
|
|
}
|
|
|
|
APR_DECLARE_NONSTD(void) fspr_terminate(void)
|
|
{
|
|
initialized--;
|
|
if (initialized) {
|
|
return;
|
|
}
|
|
fspr_pool_terminate();
|
|
|
|
WSACleanup();
|
|
|
|
TlsFree(tls_fspr_thread);
|
|
}
|
|
|
|
APR_DECLARE(void) fspr_terminate2(void)
|
|
{
|
|
fspr_terminate();
|
|
}
|