+
+ /* 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;
+ }
+
+ POOLMEM *pwszBuf = get_pool_memory(PM_FNAME);
+ POOLMEM *pwszCurDirBuf = 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 = check_pool_memory_size(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 (wcslen(name) >= 3 && (iswalpha (*name) && *(name+1) == ':'
+ && (*(name+2) == '\\' || *(name+2) == '/'))) {
+ bAddDrive = FALSE;
+ bAddCurrentPath = FALSE;
+ }
+
+ /* is path absolute? */
+ if (*name == '/' || *name == '\\')
+ bAddCurrentPath = FALSE;
+
+ /* is path relative to itself?, if yes, skip ./ */
+ if (wcslen(name) > 2 && ((wcsncmp(name, L"./", 2) == 0) || (wcsncmp(name, L".\\", 2) == 0))) {
+ name += 2;
+ }
+
+ /* is path of form '//./'? */
+ if (wcslen(name) > 3 && ((wcsncmp(name, L"//./", 4) == 0) || (wcsncmp(name, L"\\\\.\\", 4) == 0))) {
+ bAddDrive = FALSE;
+ bAddCurrentPath = FALSE;
+ bAddPrefix = FALSE;
+ if (pBIsRawPath) {
+ *pBIsRawPath = TRUE;
+ }
+ }
+
+ int nParseOffset = 0;
+
+ /* add 4 bytes header */
+ if (bAddPrefix) {
+ nParseOffset = 4;
+ wcscpy((wchar_t *)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 = check_pool_memory_size(pwszCurDirBuf, (dwCurDirPathSize+1)*sizeof(wchar_t));
+ p_GetCurrentDirectoryW(dwCurDirPathSize,(wchar_t *)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 (dwCurDirPathSize > 3 && wcsncmp((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0) {
+ /* copy drive character */
+ wcsncpy((wchar_t *)szDrive, (LPCWSTR)pwszCurDirBuf+4, 2);
+ } else {
+ /* copy drive character */
+ wcsncpy((wchar_t *)szDrive, (LPCWSTR)pwszCurDirBuf, 2);
+ }
+
+ szDrive[2] = 0;
+
+ wcscat((wchar_t *)pwszBuf, szDrive);
+ nParseOffset +=2;
+ }
+
+ /* add path if needed */
+ if (bAddCurrentPath) {
+ /* the 1 add. character is for the eventually added backslash */
+ dwBufCharsNeeded += dwCurDirPathSize+1;
+ pwszBuf = check_pool_memory_size(pwszBuf, dwBufCharsNeeded*sizeof(wchar_t));
+ /* get directory into own buffer as it may either return c:\... or \\?\C:\.... */
+
+ if (dwCurDirPathSize > 3 && wcsncmp((LPCWSTR)pwszCurDirBuf, L"\\\\?\\", 4) == 0) {
+ /* copy complete string */
+ wcscpy((wchar_t *)pwszBuf, (LPCWSTR)pwszCurDirBuf);
+ } else {
+ /* append path */
+ wcscat((wchar_t *)pwszBuf, (LPCWSTR)pwszCurDirBuf);
+ }
+
+ nParseOffset = wcslen((LPCWSTR) pwszBuf);
+
+ /* check if path ends with backslash, if not, add one */
+ if (*((wchar_t *)pwszBuf+nParseOffset-1) != L'\\') {
+ wcscat((wchar_t *)pwszBuf, L"\\");
+ nParseOffset++;
+ }
+ }
+
+
+ wchar_t *win32_name = (wchar_t *)pwszBuf+nParseOffset;
+
+ while (*name) {
+ /* Check for Unix separator and convert to Win32 */
+ if (*name == '/') {
+ *win32_name++ = '\\'; /* convert char */
+ /* If Win32 separated that is "quoted", remove quote */
+/* HELPME (Thorsten Engel): I don't understand the following part
+ * and it removes a backslash from e.g. "\\.\c:" which I need for
+ * RAW device access. So I took it out.
+ */
+#ifdef needed
+ } else if (*name == '\\' && name[1] == '\\') {
+ *win32_name++ = '\\';
+ name++; /* skip first \ */
+#endif
+ } 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 = check_pool_memory_size(pwszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(wchar_t));
+ /* create temp. buffer */
+ POOLMEM* pszBuf = get_pool_memory(PM_FNAME);
+ pszBuf = check_pool_memory_size(pszBuf, (dwBufCharsNeeded+MAX_PATH)*sizeof(wchar_t));
+ if (bAddPrefix)
+ nParseOffset = 4;
+ else
+ nParseOffset = 0;
+ wcsncpy((wchar_t *)pszBuf, (wchar_t *)pwszBuf+nParseOffset, wcslen((wchar_t *)pwszBuf)+1-nParseOffset);
+ g_pVSSPathConvertW((wchar_t *)pszBuf, (wchar_t *)pwszBuf, dwBufCharsNeeded+MAX_PATH);
+ free_pool_memory(pszBuf);
+ }
+
+ free_pool_memory(pszUCSPath);
+ free_pool_memory(pwszCurDirBuf);
+
+ Dmsg1(100, "Leave wchar_win32_path=%s\n", pwszBuf);
+ return 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;