| | @@ -190,12 +190,12 @@ |
| 190 | 190 | ** |
| 191 | 191 | */ |
| 192 | 192 | void *fossil_utf8_to_filename(const char *zUtf8){ |
| 193 | 193 | #ifdef _WIN32 |
| 194 | 194 | int nChar = MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, 0, 0); |
| 195 | | - /* Overallocate 4 chars, making some room for extended paths */ |
| 196 | | - wchar_t *zUnicode = sqlite3_malloc( (nChar+4) * sizeof(wchar_t) ); |
| 195 | + /* Overallocate 6 chars, making some room for extended paths */ |
| 196 | + wchar_t *zUnicode = sqlite3_malloc( (nChar+6) * sizeof(wchar_t) ); |
| 197 | 197 | wchar_t *wUnicode = zUnicode; |
| 198 | 198 | if( zUnicode==0 ){ |
| 199 | 199 | return 0; |
| 200 | 200 | } |
| 201 | 201 | MultiByteToWideChar(CP_UTF8, 0, zUtf8, -1, zUnicode, nChar); |
| | @@ -208,29 +208,35 @@ |
| 208 | 208 | wUnicode[0] = wUnicode[1] = wUnicode[3] = '\\'; |
| 209 | 209 | zUtf8 += 4; |
| 210 | 210 | wUnicode += 4; |
| 211 | 211 | } |
| 212 | 212 | /* |
| 213 | | - ** If (remainder of) path starts with "<drive>:/" or "<drive>:\", |
| 214 | | - ** leave the ':' intact |
| 215 | | - */ |
| 213 | + ** If there is no "\\?\" prefix but there is a drive or UNC |
| 214 | + ** path prefix and the path is larger than MAX_PATH chars, |
| 215 | + ** no Win32 API function can handle that unless it is |
| 216 | + ** prefixed with the extended path prefix. See: |
| 217 | + ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath> |
| 218 | + **/ |
| 216 | 219 | if( fossil_isalpha(zUtf8[0]) && zUtf8[1]==':' |
| 217 | | - && (zUtf8[2]=='\\' || zUtf8[2]=='/')) { |
| 220 | + && (zUtf8[2]=='\\' || zUtf8[2]=='/') ){ |
| 218 | 221 | if( wUnicode==zUnicode && nChar>MAX_PATH){ |
| 219 | | - /* |
| 220 | | - ** If there is no "\\?\" prefix but there is a drive |
| 221 | | - ** prefix and the path is larger than MAX_PATH chars, |
| 222 | | - ** no Win32 API function can handle that unless it is |
| 223 | | - ** prefixed with the extended path prefix. See: |
| 224 | | - ** <http://msdn.microsoft.com/en-us/library/aa365247(VS.85).aspx#maxpath> |
| 225 | | - **/ |
| 226 | 222 | memmove(wUnicode+4, wUnicode, nChar*sizeof(wchar_t)); |
| 227 | 223 | memcpy(wUnicode, L"\\\\?\\", 4*sizeof(wchar_t)); |
| 228 | 224 | wUnicode += 4; |
| 229 | 225 | } |
| 226 | + /* |
| 227 | + ** If (remainder of) path starts with "<drive>:/" or "<drive>:\", |
| 228 | + ** leave the ':' intact but translate the backslash to a slash. |
| 229 | + */ |
| 230 | 230 | wUnicode[2] = '\\'; |
| 231 | 231 | wUnicode += 3; |
| 232 | + }else if( wUnicode==zUnicode && nChar>MAX_PATH |
| 233 | + && (zUtf8[0]=='\\' || zUtf8[0]=='/') |
| 234 | + && (zUtf8[1]=='\\' || zUtf8[1]=='/') && zUtf8[2]!='?'){ |
| 235 | + memmove(wUnicode+6, wUnicode, nChar*sizeof(wchar_t)); |
| 236 | + memcpy(wUnicode, L"\\\\?\\UNC", 7*sizeof(wchar_t)); |
| 237 | + wUnicode += 7; |
| 232 | 238 | } |
| 233 | 239 | /* |
| 234 | 240 | ** In the remainder of the path, translate invalid characters to |
| 235 | 241 | ** characters in the Unicode private use area. This is what makes |
| 236 | 242 | ** Win32 fossil.exe work well in a Cygwin environment even when a |
| 237 | 243 | |