+
+ /* here we convert to VSS specific file name which
+ can get longer because VSS will make something like
+ \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe
+ from c:\bacula\uninstall.exe
+ */
+ Dmsg1(100, "path=%s\n", tname);
+ if (g_pVSSPathConvert != NULL) {
+ POOLMEM *pszBuf = get_pool_memory (PM_FNAME);
+ pszBuf = check_pool_memory_size(pszBuf, dwSize);
+ bstrncpy(pszBuf, tname, strlen(tname)+1);
+ g_pVSSPathConvert(pszBuf, tname, dwSize);
+ free_pool_memory(pszBuf);
+ }
+
+ Dmsg1(100, "Leave cvt_u_to_win32_path path=%s\n", tname);
+}
+
+/* Conversion of a Unix filename to a Win32 filename */
+void unix_name_to_win32(POOLMEM **win32_name, char *name)
+{
+ /* One extra byte should suffice, but we double it */
+ /* add MAX_PATH bytes for VSS shadow copy name */
+ DWORD dwSize = 2*strlen(name)+MAX_PATH;
+ *win32_name = check_pool_memory_size(*win32_name, dwSize);
+ conv_unix_to_win32_path(name, *win32_name, dwSize);
+}
+
+POOLMEM*
+make_wchar_win32_path(POOLMEM *pszUCSPath, BOOL *pBIsRawPath /*= NULL*/)
+{
+ /* created 02/27/2006 Thorsten Engel
+ *
+ * This function expects an UCS-encoded standard wchar_t in pszUCSPath and
+ * will complete the input path to an absolue path of the form \\?\c:\path\file
+ *
+ * With this trick, it is possible to have 32K characters long paths.
+ *
+ * Optionally one can use pBIsRawPath to determine id pszUCSPath contains a path
+ * to a raw windows partition.
+ */
+
+ Dmsg0(100, "Enter wchar_win32_path\n");
+ if (pBIsRawPath) {
+ *pBIsRawPath = FALSE; /* Initialize, set later */
+ }
+
+ if (!p_GetCurrentDirectoryW) {
+ Dmsg0(100, "Leave wchar_win32_path no change \n");
+ return pszUCSPath;
+ }
+
+ wchar_t *name = (wchar_t *)pszUCSPath;
+
+ /* if it has already the desired form, exit without changes */
+ if (wcslen(name) > 3 && wcsncmp(name, L"\\\\?\\", 4) == 0) {
+ Dmsg0(100, "Leave wchar_win32_path no change \n");
+ return pszUCSPath;
+ }
+
+ wchar_t *pwszBuf = (wchar_t *)get_pool_memory(PM_FNAME);
+ wchar_t *pwszCurDirBuf = (wchar_t *)get_pool_memory(PM_FNAME);
+ DWORD dwCurDirPathSize = 0;
+
+ /* get buffer with enough size (name+max 6. wchars+1 null terminator */
+ DWORD dwBufCharsNeeded = (wcslen(name)+7);
+ pwszBuf = (wchar_t *)check_pool_memory_size((POOLMEM *)pwszBuf, dwBufCharsNeeded*sizeof(wchar_t));
+
+ /* add \\?\ to support 32K long filepaths
+ it is important to make absolute paths, so we add drive and
+ current path if necessary */
+
+ BOOL bAddDrive = TRUE;
+ BOOL bAddCurrentPath = TRUE;
+ BOOL bAddPrefix = TRUE;
+
+ /* does path begin with drive? if yes, it is absolute */
+ if (iswalpha(name[0]) && name[1] == ':' && IsPathSeparator(name[2])) {
+ bAddDrive = FALSE;
+ bAddCurrentPath = FALSE;
+ }
+
+ /* is path absolute? */
+ if (IsPathSeparator(name[0]))
+ bAddCurrentPath = FALSE;
+
+ /* is path relative to itself?, if yes, skip ./ */
+ if (name[0] == '.' && IsPathSeparator(name[1])) {
+ name += 2;
+ }
+
+ /* is path of form '//./'? */
+ if (IsPathSeparator(name[0]) &&
+ IsPathSeparator(name[1]) &&
+ name[2] == '.' &&
+ IsPathSeparator(name[3])) {
+ bAddDrive = FALSE;
+ bAddCurrentPath = FALSE;
+ bAddPrefix = FALSE;
+ if (pBIsRawPath) {
+ *pBIsRawPath = TRUE;
+ }
+ }
+
+ int nParseOffset = 0;
+
+ /* add 4 bytes header */
+ if (bAddPrefix) {
+ nParseOffset = 4;
+ wcscpy(pwszBuf, L"\\\\?\\");
+ }
+
+ /* get current path if needed */
+ if (bAddDrive || bAddCurrentPath) {
+ dwCurDirPathSize = p_GetCurrentDirectoryW(0, NULL);
+ if (dwCurDirPathSize > 0) {
+ /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */
+ pwszCurDirBuf = (wchar_t *)check_pool_memory_size((POOLMEM *)pwszCurDirBuf, (dwCurDirPathSize+1)*sizeof(wchar_t));
+ p_GetCurrentDirectoryW(dwCurDirPathSize, pwszCurDirBuf);
+ } else {
+ /* we have no info for doing so */
+ bAddDrive = FALSE;
+ bAddCurrentPath = FALSE;
+ }
+ }
+
+
+ /* add drive if needed */
+ if (bAddDrive && !bAddCurrentPath) {
+ wchar_t szDrive[3];
+
+ if (IsPathSeparator(pwszCurDirBuf[0]) &&
+ IsPathSeparator(pwszCurDirBuf[1]) &&
+ pwszCurDirBuf[2] == '?' &&
+ IsPathSeparator(pwszCurDirBuf[3])) {
+ /* copy drive character */
+ szDrive[0] = pwszCurDirBuf[4];
+ } else {
+ /* copy drive character */
+ szDrive[0] = pwszCurDirBuf[0];
+ }
+
+ szDrive[1] = ':';
+ szDrive[2] = 0;
+
+ wcscat(pwszBuf, szDrive);
+ nParseOffset +=2;
+ }
+
+ /* add path if needed */
+ if (bAddCurrentPath) {
+ /* the 1 add. character is for the eventually added backslash */
+ dwBufCharsNeeded += dwCurDirPathSize+1;
+ pwszBuf = (wchar_t *)check_pool_memory_size((POOLMEM *)pwszBuf, dwBufCharsNeeded*sizeof(wchar_t));
+ /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */
+
+ if (IsPathSeparator(pwszCurDirBuf[0]) &&
+ IsPathSeparator(pwszCurDirBuf[1]) &&
+ pwszCurDirBuf[2] == '?' &&
+ IsPathSeparator(pwszCurDirBuf[3])) {
+ /* copy complete string */
+ wcscpy(pwszBuf, pwszCurDirBuf);
+ } else {
+ /* append path */
+ wcscat(pwszBuf, pwszCurDirBuf);
+ }
+
+ nParseOffset = wcslen((LPCWSTR) pwszBuf);
+
+ /* check if path ends with backslash, if not, add one */
+ if (!IsPathSeparator(pwszBuf[nParseOffset-1])) {
+ wcscat(pwszBuf, L"\\");
+ nParseOffset++;
+ }
+ }
+
+ wchar_t *win32_name = &pwszBuf[nParseOffset];
+ wchar_t *name_start = name;
+
+ while (*name) {
+ /* Check for Unix separator and convert to Win32, eliminating
+ * duplicate separators.
+ */
+ if (IsPathSeparator(*name)) {
+ *win32_name++ = '\\'; /* convert char */
+
+ /* Eliminate consecutive slashes, but not at the start so that
+ * \\.\ still works.
+ */
+ if (name_start != name && IsPathSeparator(name[1])) {
+ name++;
+ }
+ } else {
+ *win32_name++ = *name; /* copy character */
+ }
+ name++;
+ }
+
+ /* null terminate string */
+ *win32_name = 0;
+
+ /* here we convert to VSS specific file name which
+ * can get longer because VSS will make something like
+ * \\\\?\\GLOBALROOT\\Device\\HarddiskVolumeShadowCopy1\\bacula\\uninstall.exe
+ * from c:\bacula\uninstall.exe
+ */
+ if (g_pVSSPathConvertW != NULL) {
+ /* is output buffer large enough? */
+ pwszBuf = (wchar_t *)check_pool_memory_size((POOLMEM *)pwszBuf,
+ (dwBufCharsNeeded+MAX_PATH)*sizeof(wchar_t));
+ /* create temp. buffer */
+ wchar_t *pszBuf = (wchar_t *)get_pool_memory(PM_FNAME);
+ pszBuf = (wchar_t *)check_pool_memory_size((POOLMEM *)pszBuf,
+ (dwBufCharsNeeded+MAX_PATH)*sizeof(wchar_t));
+ if (bAddPrefix)
+ nParseOffset = 4;
+ else
+ nParseOffset = 0;
+ wcsncpy(pszBuf, &pwszBuf[nParseOffset], wcslen(pwszBuf)+1-nParseOffset);
+ g_pVSSPathConvertW(pszBuf, pwszBuf, dwBufCharsNeeded+MAX_PATH);
+ free_pool_memory((POOLMEM *)pszBuf);
+ }
+
+ free_pool_memory(pszUCSPath);
+ free_pool_memory((POOLMEM *)pwszCurDirBuf);
+
+ Dmsg1(100, "Leave wchar_win32_path=%s\n", pwszBuf);
+ return (POOLMEM *)pwszBuf;
+}
+
+int
+wchar_2_UTF8(char *pszUTF, const wchar_t *pszUCS, int cchChar)
+{
+ /* the return value is the number of bytes written to the buffer.
+ The number includes the byte for the null terminator. */
+
+ if (p_WideCharToMultiByte) {
+ int nRet = p_WideCharToMultiByte(CP_UTF8,0,pszUCS,-1,pszUTF,cchChar,NULL,NULL);
+ ASSERT (nRet > 0);
+ return nRet;
+ }
+ else
+ return 0;
+}
+
+int
+UTF8_2_wchar(POOLMEM **ppszUCS, const char *pszUTF)
+{
+ /* the return value is the number of wide characters written to the buffer. */
+ /* convert null terminated string from utf-8 to ucs2, enlarge buffer if necessary */
+
+ if (p_MultiByteToWideChar) {
+ /* strlen of UTF8 +1 is enough */
+ DWORD cchSize = (strlen(pszUTF)+1);
+ *ppszUCS = check_pool_memory_size(*ppszUCS, cchSize*sizeof (wchar_t));
+
+ int nRet = p_MultiByteToWideChar(CP_UTF8, 0, pszUTF, -1, (LPWSTR) *ppszUCS,cchSize);
+ ASSERT (nRet > 0);
+ return nRet;
+ }
+ else
+ return 0;