/* * COPYRIGHT: See COPYING in the top level directory * PROJECT: ReactOS pending moves operations Information tool * FILE: cmdutils/pendmoves/pendmoves.c * PURPOSE: Query information from registry about pending moves * PROGRAMMERS: Pierre Schweitzer */ #include #include #include static TCHAR * BeautifyPath(TCHAR * Path, DWORD * Len) { DWORD LocalLen = *Len; /* If there's a ! marking that existing file can be overwritten, * drop it */ if (LocalLen > 1) { if (Path[0] == _T('!')) { ++Path; --LocalLen; } } /* Remove namespace if prefixed */ if (LocalLen > 4) { if (Path[0] == _T('\\') && Path[1] == _T('?') && Path[2] == _T('?') && Path[3] == _T('\\')) { Path += 4; LocalLen -= 4; } } /* Return modified string + len */ *Len = LocalLen; return Path; } static DWORD DisplayPendingOps(TCHAR * Value, DWORD Len) { DWORD Chars, i, j, Count, SrcLen, TgtLen; TCHAR * SrcFile, * Target, * Current; /* Compute the amount of chars * NULL char isn't relaible EOF (MULTI_SZ) */ Chars = Len / sizeof(TCHAR); i = 0; Count = 0; Current = Value; /* Browse the whole string */ while (i < Chars) { /* Jump to the next NULL (end of source) */ for (j = i; j < Chars && Value[j] != 0; ++j); /* Get len & clean path */ SrcLen = _tcslen(Current); SrcFile = BeautifyPath(Current, &SrcLen); /* Source file is null - likely the end of the MULTI_SZ, quit */ if (SrcLen == 0) { break; } /* Remember position, jump to the begin of the target */ i = j; ++i; /* Update position in MULTI_SZ */ Current = Value + i; /* Jump to the next NULL (end of target) */ for (j = i; j < Chars && Value[j] != 0; ++j); /* Get len & clean path */ TgtLen = _tcslen(Current); Target = BeautifyPath(Current, &TgtLen); /* Remember position, jump to the begin of the next source */ i = j; ++i; Current = Value + i; /* Display source */ _ftprintf(stdout, _T("Source: %s\n"), SrcFile); /* If is accessible? Warn if not */ if (GetFileAttributes(SrcFile) == INVALID_FILE_ATTRIBUTES) { _ftprintf(stdout, _T("\t *** Source file lookup error: %d\n"), GetLastError()); } /* And display target - if empty, it's for deletion, mark as it */ _ftprintf(stdout, _T("Target: %s\n\n"), (_tcslen(Target) != 0 ? Target: _T("DELETE"))); /* Remember position and number of entries */ Current = Value + i; ++Count; } return Count; } int __cdecl _tmain(int argc, const TCHAR *argv[]) { HKEY hKey; LONG Ret; DWORD MaxLen, Len, Count, Type; PVOID Buffer; FILETIME LastModified; TCHAR RegistryPath[] = _T("System\\CurrentControlSet\\Control\\Session Manager"); /* Open the SMSS registry key */ Ret = RegOpenKey(HKEY_LOCAL_MACHINE, RegistryPath, &hKey); if (Ret != ERROR_SUCCESS) { _ftprintf(stderr, _T("Failed opening the registry key '%s' (%lx)\n"), RegistryPath, Ret); return 1; } /* Get last modified date + buffer length we need to allocate */ Ret = RegQueryInfoKey(hKey, NULL, NULL, NULL, NULL, NULL, NULL, NULL, NULL, &MaxLen, NULL, &LastModified); if (Ret != ERROR_SUCCESS) { RegCloseKey(hKey); _ftprintf(stderr, _T("Failed querying information for '%s' (%lx)\n"), RegistryPath, Ret); return 1; } /* No value, so no operations */ if (MaxLen == 0) { RegCloseKey(hKey); _ftprintf(stdout, _T("No pending file rename operations registered.\n\n")); return 0; } /* Allocate memory */ Buffer = HeapAlloc(GetProcessHeap(), 0, MaxLen); if (Buffer == NULL) { RegCloseKey(hKey); _ftprintf(stderr, _T("Failed allocating %d bytes\n"), MaxLen); return 1; } /* Start with PendingFileRenameOperations */ Count = 0; Len = MaxLen; Ret = RegQueryValueEx(hKey, _T("PendingFileRenameOperations"), NULL, &Type, Buffer, &Len); if (Ret == ERROR_SUCCESS && Type == REG_MULTI_SZ) { Count += DisplayPendingOps(Buffer, Len); } /* Continue with PendingFileRenameOperations2 - used if PendingFileRenameOperations is too big */ Len = MaxLen; Ret = RegQueryValueEx(hKey, _T("PendingFileRenameOperations2"), NULL, &Type, Buffer, &Len); if (Ret == ERROR_SUCCESS && Type == REG_MULTI_SZ) { Count += DisplayPendingOps(Buffer, Len); } /* Release everything */ HeapFree(GetProcessHeap(), 0, Buffer); RegCloseKey(hKey); /* If we found entries, display modification date */ if (Count != 0) { FILETIME LocalTime; SYSTEMTIME SysTime; /* Convert our UTC time to local time, and then to system time to allow easy display */ if (FileTimeToLocalFileTime(&LastModified, &LocalTime) && FileTimeToSystemTime(&LocalTime, &SysTime)) { _ftprintf(stdout, _T("Time of last update to pending moves key: %02d/%02d/%04d %02d:%02d\n\n"), SysTime.wDay, SysTime.wMonth, SysTime.wYear, SysTime.wHour, SysTime.wMinute); } } /* No operations found */ else { _ftprintf(stdout, _T("No pending file rename operations registered.\n\n")); } return 0; }