| 139 | } |
| 140 | |
| 141 | bool CRemoteCacheLink::GetStatusFromRemoteCache(const CTGitPath& Path, TGITCacheResponse* pReturnedStatus, bool bRecursive) |
| 142 | { |
| 143 | if(!EnsurePipeOpen()) |
| 144 | { |
| 145 | // We've failed to open the pipe - try and start the cache |
| 146 | // but only if the last try to start the cache was a certain time |
| 147 | // ago. If we just try over and over again without a small pause |
| 148 | // in between, the explorer is rendered unusable! |
| 149 | // Failing to start the cache can have different reasons: missing exe, |
| 150 | // missing registry key, corrupt exe, ... |
| 151 | if ((static_cast<LONGLONG>(GetTickCount64()) - m_lastTimeout) < 0) |
| 152 | return false; |
| 153 | // if we're in protected mode, don't try to start the cache: since we're |
| 154 | // here, we know we can't access it anyway and starting a new process will |
| 155 | // trigger a warning dialog in IE7+ on Vista - we don't want that. |
| 156 | if (GetProcessIntegrityLevel() < SECURITY_MANDATORY_MEDIUM_RID) |
| 157 | return false; |
| 158 | |
| 159 | if (!RunTGitCacheProcess()) |
| 160 | return false; |
| 161 | |
| 162 | // Wait for the cache to open |
| 163 | LONGLONG endTime = static_cast<LONGLONG>(GetTickCount64()) + 1000; |
| 164 | while(!EnsurePipeOpen()) |
| 165 | { |
| 166 | if ((static_cast<LONGLONG>(GetTickCount64()) - endTime) > 0) |
| 167 | { |
| 168 | m_lastTimeout = static_cast<LONGLONG>(GetTickCount64()) + 10000; |
| 169 | return false; |
| 170 | } |
| 171 | } |
| 172 | m_lastTimeout = static_cast<LONGLONG>(GetTickCount64()) + 10000; |
| 173 | } |
| 174 | |
| 175 | AutoLocker lock(m_critSec); |
| 176 | |
| 177 | DWORD nBytesRead; |
| 178 | TGITCacheRequest request; |
| 179 | request.flags = 0; |
| 180 | if(bRecursive) |
| 181 | request.flags |= TGITCACHE_FLAGS_RECUSIVE_STATUS; |
| 182 | if (Path.IsDirectoryKnown()) |
| 183 | request.flags |= TGITCACHE_FLAGS_FOLDERISKNOWN | (Path.IsDirectory() ? TGITCACHE_FLAGS_ISFOLDER : 0); |
| 184 | wcsncpy_s(request.path, Path.GetWinPath(), _countof(request.path) - 1); |
| 185 | SecureZeroMemory(&m_Overlapped, sizeof(OVERLAPPED)); |
| 186 | m_Overlapped.hEvent = m_hEvent; |
| 187 | // Do the transaction in overlapped mode. |
| 188 | // That way, if anything happens which might block this call |
| 189 | // we still can get out of it. We NEVER MUST BLOCK THE SHELL! |
| 190 | // A blocked shell is a very bad user impression, because users |
| 191 | // who don't know why it's blocked might find the only solution |
| 192 | // to such a problem is a reboot and therefore they might loose |
| 193 | // valuable data. |
| 194 | // One particular situation where the shell could hang is when |
| 195 | // the cache crashes and our crash report dialog comes up. |
| 196 | // Sure, it would be better to have no situations where the shell |
| 197 | // even can get blocked, but the timeout of 10 seconds is long enough |
| 198 | // so that users still recognize that something might be wrong and |
no test coverage detected