source: valtobtest/subversion-1.6.2/subversion/libsvn_subr/win32_xlate.c @ 3

Last change on this file since 3 was 3, checked in by valtob, 15 years ago

subversion source 1.6.2 as test

File size: 6.3 KB
Line 
1/*
2 * win32_xlate.c : Windows xlate stuff.
3 *
4 * ====================================================================
5 * Copyright (c) 2007 CollabNet.  All rights reserved.
6 *
7 * This software is licensed as described in the file COPYING, which
8 * you should have received as part of this distribution.  The terms
9 * are also available at http://subversion.tigris.org/license-1.html.
10 * If newer versions of this license are posted there, you may use a
11 * newer version instead, at your option.
12 *
13 * This software consists of voluntary contributions made by many
14 * individuals.  For exact contribution history, see the revision
15 * history and logs, available at http://subversion.tigris.org/.
16 * ====================================================================
17 */
18
19#ifdef WIN32
20
21/* Define _WIN32_DCOM for CoInitializeEx(). */
22#define _WIN32_DCOM
23
24/* We must include windows.h ourselves or apr.h includes it for us with
25   many ignore options set. Including Winsock is required to resolve IPv6
26   compilation errors. APR_HAVE_IPV6 is only defined after including
27   apr.h, so we can't detect this case here. */
28
29/* winsock2.h includes windows.h */
30#include <winsock2.h>
31#include <Ws2tcpip.h>
32#include <mlang.h>
33
34#include <apr.h>
35#include <apr_errno.h>
36#include <apr_portable.h>
37
38#include "svn_pools.h"
39#include "svn_string.h"
40#include "svn_utf.h"
41
42#include "win32_xlate.h"
43
44typedef struct win32_xlate_t
45{
46  UINT from_page_id;
47  UINT to_page_id;
48} win32_xlate_t;
49
50static apr_status_t
51get_page_id_from_name(UINT *page_id_p, const char *page_name, apr_pool_t *pool)
52{
53  IMultiLanguage * mlang = NULL;
54  HRESULT hr;
55  MIMECSETINFO page_info;
56  WCHAR ucs2_page_name[128];
57
58  if (page_name == SVN_APR_DEFAULT_CHARSET)
59    {
60        *page_id_p = CP_ACP;
61        return APR_SUCCESS;
62    }
63  else if (page_name == SVN_APR_LOCALE_CHARSET)
64    {
65      OSVERSIONINFO ver_info;
66      ver_info.dwOSVersionInfoSize = sizeof(ver_info);
67
68      /* CP_THREAD_ACP supported only on Windows 2000 and later.*/
69      if (GetVersionEx(&ver_info) && ver_info.dwMajorVersion >= 5
70          && ver_info.dwPlatformId == VER_PLATFORM_WIN32_NT)
71        {
72          *page_id_p = CP_THREAD_ACP;
73          return APR_SUCCESS;
74        }
75
76      /* CP_THREAD_ACP isn't supported on current system, so get locale
77         encoding name from APR. */
78      page_name = apr_os_locale_encoding(pool);
79    }
80  else if (!strcmp(page_name, "UTF-8"))
81    {
82      *page_id_p = CP_UTF8;
83      return APR_SUCCESS;
84    }
85
86  /* Use codepage identifier nnn if the codepage name is in the form
87     of "CPnnn".
88     We need this code since apr_os_locale_encoding() and svn_cmdline_init()
89     generates such codepage names even if they are not valid IANA charset
90     name. */
91  if ((page_name[0] == 'c' || page_name[0] == 'C')
92      && (page_name[1] == 'p' || page_name[1] == 'P'))
93    {
94      *page_id_p = atoi(page_name + 2);
95      return APR_SUCCESS;
96    }
97
98  hr = CoCreateInstance(&CLSID_CMultiLanguage, NULL, CLSCTX_INPROC_SERVER,
99                        &IID_IMultiLanguage, (void **) &mlang);
100
101  if (FAILED(hr))
102    return APR_EGENERAL;
103
104  /* Convert page name to wide string. */
105  MultiByteToWideChar(CP_UTF8, 0, page_name, -1, ucs2_page_name,
106                      sizeof(ucs2_page_name) / sizeof(ucs2_page_name[0]));
107  memset(&page_info, 0, sizeof(page_info));
108  hr = mlang->lpVtbl->GetCharsetInfo(mlang, ucs2_page_name, &page_info);
109  if (FAILED(hr))
110    {
111      mlang->lpVtbl->Release(mlang);
112      return APR_EINVAL;
113    }
114
115  if (page_info.uiInternetEncoding)
116    *page_id_p = page_info.uiInternetEncoding;
117  else
118    *page_id_p = page_info.uiCodePage;
119
120  mlang->lpVtbl->Release(mlang);
121
122  return APR_SUCCESS;
123}
124
125apr_status_t
126svn_subr__win32_xlate_open(win32_xlate_t **xlate_p, const char *topage,
127                           const char *frompage, apr_pool_t *pool)
128{
129  UINT from_page_id, to_page_id;
130  apr_status_t apr_err = APR_SUCCESS;
131  win32_xlate_t *xlate;
132  HRESULT hr;
133
134  /* First try to initialize for apartment-threaded object concurrency. */
135  hr = CoInitializeEx(NULL, COINIT_APARTMENTTHREADED);
136  if (hr == RPC_E_CHANGED_MODE)
137    {
138      /* COM already initalized for multi-threaded object concurrency. We are
139         neutral to object concurrency so try to initalize it in the same way
140         for us. */
141      hr = CoInitializeEx(NULL, COINIT_MULTITHREADED);
142    }
143
144  if (FAILED(hr))
145    return APR_EGENERAL;
146
147  apr_err = get_page_id_from_name(&to_page_id, topage, pool);
148  if (apr_err == APR_SUCCESS)
149    apr_err = get_page_id_from_name(&from_page_id, frompage, pool);
150
151  if (apr_err == APR_SUCCESS)
152    {
153      xlate = apr_palloc(pool, sizeof(*xlate));
154      xlate->from_page_id = from_page_id;
155      xlate->to_page_id = to_page_id;
156
157      *xlate_p = xlate;
158    }
159
160  CoUninitialize();
161  return apr_err;
162}
163
164apr_status_t
165svn_subr__win32_xlate_to_stringbuf(win32_xlate_t *handle,
166                                   const char *src_data,
167                                   apr_size_t src_length,
168                                   svn_stringbuf_t **dest,
169                                   apr_pool_t *pool)
170{
171  WCHAR * wide_str;
172  int retval, wide_size;
173
174  *dest = svn_stringbuf_create("", pool);
175
176  if (src_length == 0)
177    return APR_SUCCESS;
178
179  retval = MultiByteToWideChar(handle->from_page_id, 0, src_data, src_length,
180                               NULL, 0);
181  if (retval == 0)
182    return apr_get_os_error();
183
184  wide_size = retval;
185
186  /* Allocate temporary buffer for small strings on stack instead of heap. */
187  if (wide_size <= MAX_PATH)
188    {
189      wide_str = alloca(wide_size * sizeof(WCHAR));
190    }
191  else
192    {
193      wide_str = apr_palloc(pool, wide_size * sizeof(WCHAR));
194    }
195
196  retval = MultiByteToWideChar(handle->from_page_id, 0, src_data, src_length,
197                               wide_str, wide_size);
198
199  if (retval == 0)
200    return apr_get_os_error();
201
202  retval = WideCharToMultiByte(handle->to_page_id, 0, wide_str, wide_size,
203                               NULL, 0, NULL, NULL);
204
205  if (retval == 0)
206    return apr_get_os_error();
207
208  /* Ensure that buffer is enough to hold result string and termination
209     character. */
210  svn_stringbuf_ensure(*dest, retval + 1);
211  (*dest)->len = retval;
212
213  retval = WideCharToMultiByte(handle->to_page_id, 0, wide_str, wide_size,
214                               (*dest)->data, (*dest)->len, NULL, NULL);
215  if (retval == 0)
216    return apr_get_os_error();
217
218  (*dest)->len = retval;
219  return APR_SUCCESS;
220}
221
222#endif /* WIN32 */
Note: See TracBrowser for help on using the repository browser.