Leaked source code of windows server 2003
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 
 

2293 lines
66 KiB

/*++
Copyright (c) 1997-1999 Microsoft Corporation
Module Name:
frs.c
Abstract:
This module is a development tool. It exercises the dcpromo and poke
APIs.
Author:
Billy J. Fuller 12-Dec-1997
Environment
User mode winnt
--*/
#include <ntreppch.h>
#pragma hdrstop
#include <frs.h>
#include <ntfrsapi.h>
#define FREE(_x_) { if (_x_) LocalFree(_x_); _x_ = NULL; }
VOID
Win32ToMsg (
IN PWCHAR Prefix,
IN DWORD WStatus
)
/*++
Routine Description:
Translate a error code into a error message using FormatMessage()
and print to stderr. If no message is available, the error code
is printed in decimal and hex.
Arguments:
Prefix - prefix to error message
WStatus - Standard win32 error code.
Return Value:
None.
--*/
{
DWORD NumChar;
PWCHAR Buffer;
if (WIN_SUCCESS(WStatus)) {
return;
}
// Use the system formatter for standard error codes
NumChar = FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM |
FORMAT_MESSAGE_ALLOCATE_BUFFER,
NULL,
WStatus,
0,
(PWCHAR)&Buffer,
0,
NULL);
if (NumChar) {
fprintf(stderr, "%ws %ws\n", Prefix, Buffer);
} else {
fprintf(stderr, "%ws Status %d (0x%08x)\n", Prefix, WStatus, WStatus);
}
}
VOID
Usage(
IN DWORD ExitStatus
)
/*++
Routine Description:
Print usage and exit
Arguments:
ExitStatus - exits with this status
Return Value:
Exit(ExitStatus)
--*/
{
printf("frs restore | backup [/all /auth /nonauth /primary /system /ds /normal /key /restart] [dir nonauth|primary|auth ....]\n");
printf("\t = excercise the backup/restore api\n");
printf("\t WARNING - deletes database\n");
printf("\trestore = excercise restore\n");
printf("\tbackup = excercise backup\n");
printf("\t/all = set all flag (all dirs)\n");
printf("\t/auth = set auth flag\n");
printf("\t/nonauth = set nonauth flag\n");
printf("\t/primary = set primary flag\n");
printf("\t/system = set system flag\n");
printf("\t/ds = set active directory flag\n");
printf("\t/normal = set normal flag\n");
printf("\t/key = expect keypath-when-done\n");
printf("\t/restart = set restart-service-when-done\n");
printf("\tSUPPORTED = restore /system /all /nonauth /restart\n");
printf("\tSUPPORTED = restore /system /all /primary /restart\n");
printf("\tSUPPORTED = restore /system /all /nonauth /key \n");
printf("\tSUPPORTED = restore /system /all /primary /key \n");
printf("\tSUPPORTED = restore /ds /all /nonauth /restart\n");
printf("\tSUPPORTED = restore /ds /all /primary /restart\n");
printf("\tSUPPORTED = restore /ds /all /nonauth /key \n");
printf("\tSUPPORTED = restore /ds /all /primary /key \n");
printf("\tSUPPORTED = restore /ds /all /nonauth /restart dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /ds /all /primary /restart dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /ds /all /nonauth /key dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /ds /all /primary /key dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /ds /nonauth /restart dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /ds /primary /restart dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /ds /nonauth /key dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /ds /primary /key dir primary|nonauth ...\n");
printf("\tSUPPORTED = restore /normal /all /auth\n");
printf("\tSUPPORTED = backup /normal\n");
printf("\n");
printf("frs install stagepath [targetpath]\n");
printf("\t = install the staging file\n");
printf("\tstagepath = path of staging file.\n");
printf("\ttargetpath= path of target file to OVERWRITE!.\n");
printf("\n");
printf("frs [idtable|inlog|outlog] [computer]\n");
printf("\t = enumerate the service's idtable/inlog/outlog \n");
printf("\tcomputer = talk to the NtFrs service on this machine.\n");
printf("\n");
printf("frs [memory|threads|stage] [computer]\n");
printf("\t = list the service's memory usage\n");
printf("\tcomputer = talk to the NtFrs service on this machine.\n");
printf("\n");
printf("frs ds [computer]\n");
printf("\t = list the service's view of the DS\n");
printf("\tcomputer = talk to the NtFrs service on this machine.\n");
printf("\n");
printf("frs sets [computer]\n");
printf("\t = list the active replica sets\n");
printf("\tcomputer = talk to the NtFrs service on this machine.\n");
printf("\n");
printf("frs version [computer]\n");
printf("\t = list the api and service versions\n");
printf("\tcomputer = talk to the NtFrs service on this machine.\n");
printf("\n");
printf("frs poll [/quickly[=[N]]] [/slowly[=[N]]] [/now] [computer]\n");
printf("\t = list the current polling intervals.\n");
printf("\tnow = Poll now.\n");
printf("\tquickly = Poll quickly until stable configuration retrieved.\n");
printf("\tquickly= = Poll quickly every default minutes.\n");
printf("\tquickly=N = Poll quickly every N minutes.\n");
printf("\tslowly = Poll slowly until stable configuration retrieved.\n");
printf("\tslowly= = Poll slowly every default minutes.\n");
printf("\tslowly=N = Poll slowly every N minutes.\n");
printf("\tcomputer = talk to the NtFrs service on this machine.\n");
printf("\n");
printf("frs promote Parent Account Password Set Type Primary Stage Root\n");
printf("\tParent = RPC bindable name of parent DC.\n");
printf("\tAccount = Account on Parent.\n");
printf("\tPassword = Password for Account on Parent.\n");
printf("\tSet = Name of replica set.\n");
printf("\tType = Type of replica set (Enterprise or Domain).\n");
printf("\tPrimary = Is this the primary member? (1=yes or 0=no)\n");
printf("\tStage = Staging path.\n");
printf("\tRoot = Root path.\n");
printf("\n");
printf("frs demote Set\n");
printf("\tSet = Name of replica set.\n");
printf("\n");
printf("frs promotesysvols Parent Account Password PrimaryEnterprise PrimaryDomain Stage RootEnterprise RootDomain\n");
printf("\tParent = RPC bindable name of parent DC.\n");
printf("\tAccount = Account on Parent.\n");
printf("\tPassword = Password for Account on Parent.\n");
printf("\tPrimaryEnterprise = Is this the primary member? (1=yes or 0=no)\n");
printf("\tPrimaryDomain = Is this the primary member? (1=yes or 0=no)\n");
printf("\tStage = Staging path.\n");
printf("\tRootEnterprise = Root path.\n");
printf("\tRootDomain = Root path.\n");
printf("\n");
printf("frs demotesysvols\n");
exit(ExitStatus);
}
PWCHAR *
ConvertArgv(
DWORD argc,
PCHAR *argv
)
/*++
Routine Description:
Convert short char argv into wide char argv
Arguments:
argc - From main
argv - From main
Return Value:
Address of the new argv
--*/
{
PWCHAR *wideargv;
wideargv = LocalAlloc(LMEM_FIXED, (argc + 1) * sizeof(PWCHAR));
if (wideargv == NULL) {
fprintf(stderr, "Can't get memory; Win32 Status %d\n",
GetLastError());
exit(1);
}
wideargv[argc] = NULL;
while (argc-- >= 1) {
wideargv[argc] = LocalAlloc(LMEM_FIXED,
(strlen(argv[argc]) + 1) * sizeof(WCHAR));
if (wideargv[argc] == NULL) {
fprintf(stderr, "Can't get memory; Win32 Status %d\n",
GetLastError());
exit(1);
}
wsprintf(wideargv[argc], L"%hs", argv[argc]);
FRS_WCSLWR(wideargv[argc]);
}
return wideargv;
}
DWORD
Display(
IN PWCHAR StrW
)
/*++
Routine Description:
Display the string
Arguments:
StrW
Return Value:
None.
--*/
{
printf("DISPLAY %ws\n", StrW);
return ERROR_SUCCESS;
}
DWORD
FrsErrorCallBack(
IN PWCHAR Msg,
IN DWORD WStatus
)
/*++
Routine Description:
Arguments:
Return Value:
--*/
{
fprintf(stderr, "%ws (%d)\n", Msg, WStatus);
return ERROR_SUCCESS;
}
VOID
ProcessPromote(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Process the command line for the subcommand promote.
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
PWCHAR Parent;
PWCHAR Account;
PWCHAR Password;
PWCHAR Set;
PWCHAR Type;
PWCHAR Primary;
PWCHAR Stage;
PWCHAR Root;
DWORD IsPrimary;
if (argc != 10) {
Usage(1);
}
Parent = Argv[2];
Account = Argv[3];
Password = Argv[4];
Set = Argv[5];
Type = Argv[6];
Primary = Argv[7];
Stage = Argv[8];
Root = Argv[9];
//
// No account; use impersonation
//
if (Account && !*Account) {
Account = NULL;
Password = NULL;
}
printf("%ws %ws %ws ... %ws\n",
Argv[0], Argv[1], Parent, Root);
printf("PROMOTE WITH COMMIT\n");
//
// Check params
//
if (_wcsicmp(Primary, L"0") && _wcsicmp(Primary, L"1")) {
printf("Primary must be 0 or 1; not %ws\n", Primary);
Usage(1);
}
if (_wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE) &&
_wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_DOMAIN)) {
printf("Type must be Enterprise or Domain; not %ws\n", Type);
Usage(1);
}
IsPrimary = wcstoul(Primary, NULL, 10);
//
// Prepare
//
WStatus = NtFrsApi_PrepareForPromotionW( FrsErrorCallBack );
if (WStatus == ERROR_SUCCESS) {
printf("success prepare\n");
} else {
printf("failure prepare %08x\n", WStatus);
Win32ToMsg (L"Promote:", WStatus);
}
//
// Start
//
WStatus = NtFrsApi_StartPromotionW(Parent,
Account,
Password,
Display,
FrsErrorCallBack,
Set,
Type,
IsPrimary,
Stage,
Root);
if (WStatus == ERROR_SUCCESS) {
printf("success start\n");
} else {
printf("failure start %08x\n", WStatus);
Win32ToMsg (L"Promote:", WStatus);
}
//
// Wait
//
printf("Waiting on promotion\n");
WStatus = NtFrsApi_WaitForPromotionW(30 * 60 * 1000, FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("Wait succeeded\n");
Win32ToMsg (L"Promote:", WStatus);
} else {
printf("failure wait %08x\n", WStatus);
Win32ToMsg (L"Promote:", WStatus);
}
//
// Commit (or Abort)
//
// WStatus = NtFrsApi_AbortPromotionW();
WStatus = NtFrsApi_CommitPromotionW(0, FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success commit\n");
} else {
printf("failure commit %08x\n", WStatus);
Win32ToMsg (L"Promote:", WStatus);
}
exit(0);
}
VOID
ProcessPromoteSysVols(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Process the command line for the subcommand promotesysvols.
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
PWCHAR Parent;
PWCHAR Account;
PWCHAR Password;
PWCHAR PrimaryEnterprise;
PWCHAR PrimaryDomain;
PWCHAR Stage;
PWCHAR RootEnterprise;
PWCHAR RootDomain;
DWORD IsPrimaryEnterprise;
DWORD IsPrimaryDomain;
DWORD WaitStatus;
if (argc != 10) {
Usage(1);
}
Parent = Argv[2];
Account = Argv[3];
Password = Argv[4];
PrimaryEnterprise = Argv[5];
PrimaryDomain = Argv[6];
Stage = Argv[7];
RootEnterprise = Argv[8];
RootDomain = Argv[9];
printf("%ws %ws %ws %ws %ws %ws %ws %ws %ws %ws\n",
Argv[0], Argv[1],
Parent,
Account,
Password,
PrimaryEnterprise,
PrimaryDomain,
Stage,
RootEnterprise,
RootDomain);
printf("PROMOTE SYSVOLS WITH COMMIT\n");
//
// Check params
//
if (_wcsicmp(PrimaryEnterprise, L"0") &&
_wcsicmp(PrimaryEnterprise, L"1")) {
printf("Primary Enterprise must be 0 or 1; not %ws\n",
PrimaryEnterprise);
Usage(1);
}
if (_wcsicmp(PrimaryDomain, L"0") &&
_wcsicmp(PrimaryDomain, L"1")) {
printf("Primary Domain must be 0 or 1; not %ws\n",
PrimaryDomain);
Usage(1);
}
IsPrimaryEnterprise = wcstoul(PrimaryEnterprise, NULL, 10);
IsPrimaryDomain = wcstoul(PrimaryDomain, NULL, 10);
//
// Prepare
//
WStatus = NtFrsApi_PrepareForPromotionW(FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success sysvol prepare\n");
} else {
printf("ERROR sysvol prepare %d\n", WStatus);
}
//
// Start Enterprise
//
WStatus = NtFrsApi_StartPromotionW(Parent,
Account,
Password,
Display,
FrsErrorCallBack,
NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE,
NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE,
IsPrimaryEnterprise,
Stage,
RootEnterprise);
if (WStatus == ERROR_SUCCESS) {
printf("success sysvol enterprise start\n");
} else {
printf("ERROR sysvol enterprise start %d\n", WStatus);
}
//
// Start Domain
//
WStatus = NtFrsApi_StartPromotionW(Parent,
Account,
Password,
Display,
FrsErrorCallBack,
NTFRSAPI_REPLICA_SET_TYPE_DOMAIN,
NTFRSAPI_REPLICA_SET_TYPE_DOMAIN,
IsPrimaryDomain,
Stage,
RootDomain);
if (WStatus == ERROR_SUCCESS) {
printf("success sysvol domain start\n");
} else {
printf("ERROR sysvol domain start %d\n", WStatus);
}
//
// Wait
//
printf("Waiting on promotion\n");
WaitStatus = NtFrsApi_WaitForPromotionW(5 * 60 * 1000,FrsErrorCallBack);
if (WaitStatus == WAIT_TIMEOUT) {
printf("Wait timed out\n");
} else if (WaitStatus == WAIT_FAILED) {
WStatus = GetLastError();
printf("ERROR wait sysvols %d\n", WStatus);
} else {
printf("Wait sysvols succeeded\n");
}
//
// Commit (or Abort)
//
// WStatus = NtFrsApi_AbortPromotionW();
WStatus = NtFrsApi_CommitPromotionW(0,FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success sysvols commit\n");
} else {
printf("ERROR sysvols commit %d\n", WStatus);
}
exit(0);
}
VOID
ProcessPromoteAbort(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Process the command line for the subcommand promoteabort.
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
PWCHAR Parent;
PWCHAR Account;
PWCHAR Password;
PWCHAR Set;
PWCHAR Type;
PWCHAR Primary;
PWCHAR Stage;
PWCHAR Root;
DWORD IsPrimary;
DWORD WaitStatus;
if (argc != 10) {
Usage(1);
}
Parent = Argv[2];
Account = Argv[3];
Password = Argv[4];
Set = Argv[5];
Type = Argv[6];
Primary = Argv[7];
Stage = Argv[8];
Root = Argv[9];
printf("%ws %ws %ws ... %ws\n",
Argv[0], Argv[1], Parent, Root);
printf("PROMOTE WITH ABORT\n");
//
// Check params
//
if (_wcsicmp(Primary, L"0") && _wcsicmp(Primary, L"1")) {
printf("Primary must be 0 or 1; not %ws\n", Primary);
Usage(1);
}
if (_wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE) &&
_wcsicmp(Type, NTFRSAPI_REPLICA_SET_TYPE_DOMAIN)) {
printf("Type must be Enterprise or Domain; not %ws\n", Type);
Usage(1);
}
IsPrimary = wcstoul(Primary, NULL, 10);
//
// Prepare
//
WStatus = NtFrsApi_PrepareForPromotionW(FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success prepare\n");
} else {
printf("failure prepare %d\n", WStatus);
}
//
// Start
//
WStatus = NtFrsApi_StartPromotionW(Parent,
Account,
Password,
NULL,
FrsErrorCallBack,
Set,
Type,
IsPrimary,
Stage,
Root);
if (WStatus == ERROR_SUCCESS) {
printf("success start\n");
} else {
printf("failure start %d\n", WStatus);
}
//
// Abort
//
WStatus = NtFrsApi_AbortPromotionW();
if (WStatus == ERROR_SUCCESS) {
printf("success abort\n");
} else {
printf("failure abort %d\n", WStatus);
}
exit(0);
}
VOID
ProcessDemote(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Process the command line for the subcommand demote.
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
PWCHAR Set;
DWORD WaitStatus;
if (argc != 3) {
Usage(1);
}
Set = Argv[2];
printf("%ws %ws %ws\n", Argv[0], Argv[1], Set);
printf("***** DEMOTE WITH COMMIT\n");
//
// Prepare
//
WStatus = NtFrsApi_PrepareForDemotionW(FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote prepare\n");
} else {
printf("failure demote prepare %d\n", WStatus);
}
//
// Start
//
WStatus = NtFrsApi_StartDemotionW(Set,FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote start\n");
} else {
printf("failure demote start %d\n", WStatus);
}
//
// Wait
//
WStatus = NtFrsApi_WaitForDemotionW(5 * 60 * 1000,FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote wait\n");
} else {
printf("failure demote wait %d\n", WStatus);
}
//
// Wait
//
printf("Waiting on demotion\n");
WaitStatus = NtFrsApi_WaitForPromotionW(5 * 60 * 1000,FrsErrorCallBack);
if (WaitStatus == WAIT_TIMEOUT) {
printf("Wait timed out\n");
} else if (WaitStatus == WAIT_FAILED) {
WStatus = GetLastError();
printf("failure wait %d\n", WStatus);
} else {
printf("Wait succeeded\n");
}
//
// Commit (or Abort)
//
WStatus = NtFrsApi_CommitDemotionW(0,FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote commit\n");
} else {
printf("failure demote commit %d\n", WStatus);
}
exit(0);
}
VOID
ProcessDemoteSysVols(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Process the command line for the subcommand demotesysvols.
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
DWORD WaitStatus;
if (argc != 2) {
Usage(1);
}
printf("%ws %ws\n", Argv[0], Argv[1]);
printf("***** DEMOTE SYSVOLS WITH COMMIT\n");
//
// Prepare
//
WStatus = NtFrsApi_PrepareForDemotionW(FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote sysvols prepare\n");
} else {
printf("ERROR demote sysvols prepare %d\n", WStatus);
}
//
// Start
//
WStatus = NtFrsApi_StartDemotionW(NTFRSAPI_REPLICA_SET_TYPE_ENTERPRISE,NULL);
if (WStatus == ERROR_SUCCESS) {
printf("success demote enterprise start\n");
} else {
printf("ERROR demote enterprise start %d\n", WStatus);
}
//
// Start
//
WStatus = NtFrsApi_StartDemotionW(NTFRSAPI_REPLICA_SET_TYPE_DOMAIN, FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote domain start\n");
} else {
printf("ERROR demote domain start %d\n", WStatus);
}
//
// Wait
//
WStatus = NtFrsApi_WaitForDemotionW(5 * 60 * 1000, FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote sysvols wait\n");
} else {
printf("ERROR demote sysvols wait %d\n", WStatus);
}
//
// Wait
//
printf("Waiting on demotion\n");
WaitStatus = NtFrsApi_WaitForPromotionW(5 * 60 * 1000, FrsErrorCallBack);
if (WaitStatus == WAIT_TIMEOUT) {
printf("Wait timed out\n");
} else if (WaitStatus == WAIT_FAILED) {
WStatus = GetLastError();
printf("ERROR wait %d\n", WStatus);
} else {
printf("Wait demote sysvols succeeded\n");
}
//
// Commit (or Abort)
//
WStatus = NtFrsApi_CommitDemotionW(0, FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote sysvols commit\n");
} else {
printf("ERROR demote sysvols commit %d\n", WStatus);
}
exit(0);
}
VOID
ProcessDemoteAbort(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Process the command line for the subcommand demoteabort.
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
PWCHAR Set;
DWORD WaitStatus;
if (argc != 3) {
Usage(1);
}
Set = Argv[2];
printf("%ws %ws %ws\n", Argv[0], Argv[1], Set);
printf("***** DEMOTE WITH ABORT\n");
//
// Prepare
//
WStatus = NtFrsApi_PrepareForDemotionW(FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote prepare\n");
} else {
printf("failure demote prepare %d\n", WStatus);
}
//
// Start
//
WStatus = NtFrsApi_StartDemotionW(Set, FrsErrorCallBack);
if (WStatus == ERROR_SUCCESS) {
printf("success demote start\n");
} else {
printf("failure demote start %d\n", WStatus);
}
//
// Abort
//
WStatus = NtFrsApi_AbortDemotionW();
if (WStatus == ERROR_SUCCESS) {
printf("success demote abort\n");
} else {
printf("failure demote abort %d\n", WStatus);
}
exit(0);
}
VOID
ProcessPoll(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Process the command line for the subcommand poll.
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
DWORD i;
ULONG LongInterval;
ULONG ShortInterval;
ULONG UseShortInterval;
ULONG Interval;
DWORD ComputerLen;
PWCHAR ComputerName;
BOOL SetInterval;
//
// Initialize the input parameters
//
LongInterval = 0;
ShortInterval = 0;
UseShortInterval = 0;
ComputerName = NULL;
SetInterval = FALSE;
for (i = 2; i < argc; ++i) {
//
// Process options for poll
//
//
// Not a parameter; must be the computer name
//
if (*Argv[i] != L'/' && *Argv[i] != L'-') {
if (ComputerName) {
fprintf(stderr, "Multiple computer names are not allowed\n");
Usage(1);
}
ComputerName = Argv[i];
//
// /?
//
} else if (wcsstr(Argv[i] + 1, L"?") == Argv[i] + 1) {
Usage(0);
//
// /quickly
//
} else if (!_wcsnicmp(Argv[i], L"/quickly", 8)) {
SetInterval = TRUE;
UseShortInterval = 1;
if (*(Argv[i] + 8) != L'\0') {
if (*(Argv[i] + 8) != L'=') {
fprintf(stderr, "Don't understand %ws\n", Argv[i]);
Usage(1);
}
if (*(Argv[i] + 9) == L'\0') {
ShortInterval = NTFRSAPI_DEFAULT_SHORT_INTERVAL;
} else {
ShortInterval = wcstoul(Argv[i] + 9, NULL, 10);
}
if (ShortInterval < NTFRSAPI_MIN_INTERVAL ||
ShortInterval > NTFRSAPI_MAX_INTERVAL) {
fprintf(stderr, "Interval must be between %d and %d\n",
NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL);
Usage(1);
}
}
//
// /slowly
//
} else if (!_wcsnicmp(Argv[i], L"/slowly", 7)) {
SetInterval = TRUE;
if (*(Argv[i] + 7) != L'\0') {
if (*(Argv[i] + 7) != L'=') {
fprintf(stderr, "Don't understand %ws\n", Argv[i]);
Usage(1);
}
if (*(Argv[i] + 8) == L'\0') {
LongInterval = NTFRSAPI_DEFAULT_LONG_INTERVAL;
} else {
LongInterval = wcstoul(Argv[i] + 8, NULL, 10);
}
if (LongInterval < NTFRSAPI_MIN_INTERVAL ||
LongInterval > NTFRSAPI_MAX_INTERVAL) {
fprintf(stderr, "Interval must be between %d and %d\n",
NTFRSAPI_MIN_INTERVAL, NTFRSAPI_MAX_INTERVAL);
Usage(1);
}
}
//
// /now
//
} else if (!_wcsnicmp(Argv[i], L"/now", 4)) {
SetInterval = TRUE;
if (*(Argv[i] + 4) != L'\0') {
fprintf(stderr, "Don't understand %ws\n", Argv[i]);
Usage(1);
}
//
// Don't understand
//
} else {
fprintf(stderr, "Don't understand %ws\n", Argv[i]);
Usage(1);
}
}
if (SetInterval) {
//
// Set the interval and initiate a new polling cycle
//
WStatus = NtFrsApi_Set_DsPollingIntervalW(ComputerName,
UseShortInterval,
LongInterval,
ShortInterval);
if (!WIN_SUCCESS(WStatus)) {
Win32ToMsg(L"Can't set interval:", WStatus);
exit(1);
}
} else {
//
// Get the current polling cycles
//
WStatus = NtFrsApi_Get_DsPollingIntervalW(ComputerName,
&Interval,
&LongInterval,
&ShortInterval);
if (!WIN_SUCCESS(WStatus)) {
Win32ToMsg(L"Can't get intervals:", WStatus);
exit(1);
}
printf("Current Interval: %6d minutes\n", Interval);
printf("Short Interval : %6d minutes\n", ShortInterval);
printf("Long Interval : %6d minutes\n", LongInterval);
}
exit(0);
}
VOID
ProcessDump(
IN DWORD argc,
IN PWCHAR *Argv,
IN DWORD TypeOfInformation
)
/*++
Routine Description:
Dump bunches of stuff
Arguments:
argc
Argv
TypeOfInformation
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
PCHAR Line;
BOOL FirstTime = TRUE;
PVOID Info = NULL;
PWCHAR ComputerName = NULL;
if (argc > 2) {
ComputerName = Argv[2];
}
do {
WStatus = NtFrsApi_InfoW(ComputerName,
TypeOfInformation,
0,
&Info);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr, "ERROR NtFrsApi_InfoW() Error %d\n", WStatus);
NtFrsApi_InfoFreeW(&Info);
exit(1);
}
if (Info) {
if (!FirstTime) {
printf("===== THE FOLLOWING INFO MAY BE INCONSISTENT DUE TO REFETCH =====\n");
}
FirstTime = FALSE;
Line = NULL;
do {
WStatus = NtFrsApi_InfoLineW(Info, &Line);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr, "ERROR NtFrsApi_InfoLineW() Error %d\n", WStatus);
NtFrsApi_InfoFreeW(&Info);
exit(1);
}
if (Line) {
printf("%s", Line);
}
} while (Line);
}
} while (Info);
exit(0);
}
typedef struct _DIRS DIRS, *PDIRS;
struct _DIRS {
PDIRS Next;
PWCHAR Dir;
PVOID BurSet;
};
VOID
ProcessBackupRestore(
IN DWORD argc,
IN PWCHAR *Argv,
IN DWORD BurFlags
)
/*++
Routine Description:
Dump replicated dirs
Arguments:
argc
Argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
DWORD i;
DWORD BurSetIndex;
DWORD DestroyBurFlags = NTFRSAPI_BUR_FLAGS_NONE;
PVOID BurContext;
PVOID BurSet;
BOOL IsSysvol;
BOOL ExpectKey = FALSE;
BOOL Spin = FALSE;
HKEY HKey;
PWCHAR DirPath;
PWCHAR DirType;
PDIRS Dirs = NULL;
PDIRS Dir = NULL;
DWORD BufferSize;
WCHAR Buffer[1024];
DWORD Buffer2Size;
WCHAR Buffer2[1024];
DWORD FiltersSize;
WCHAR Filters[1024];
PWCHAR Str;
for (i = 2; i < argc; ++i) {
printf("%ws\n", Argv[i]);
if (!_wcsicmp(Argv[i], L"/auth")) {
BurFlags |= NTFRSAPI_BUR_FLAGS_AUTHORITATIVE;
} else if (!_wcsicmp(Argv[i], L"/nonauth")) {
BurFlags |= NTFRSAPI_BUR_FLAGS_NON_AUTHORITATIVE;
} else if (!_wcsicmp(Argv[i], L"/primary")) {
BurFlags |= NTFRSAPI_BUR_FLAGS_PRIMARY;
} else if (!_wcsicmp(Argv[i], L"/system")) {
BurFlags |= NTFRSAPI_BUR_FLAGS_SYSTEM;
} else if (!_wcsicmp(Argv[i], L"/ds")) {
BurFlags |= NTFRSAPI_BUR_FLAGS_ACTIVE_DIRECTORY;
} else if (!_wcsicmp(Argv[i], L"/normal")) {
BurFlags |= NTFRSAPI_BUR_FLAGS_NORMAL;
} else if (!_wcsicmp(Argv[i], L"/all")) {
BurFlags |= NTFRSAPI_BUR_FLAGS_ALL_DIRECTORIES_AND_VOLUMES;
} else if (!_wcsicmp(Argv[i], L"/restart")) {
DestroyBurFlags |= NTFRSAPI_BUR_FLAGS_RESTART;
} else if (!_wcsicmp(Argv[i], L"/unknown")) {
BurFlags |= 0x80000000;
} else if (!_wcsicmp(Argv[i], L"/destroyunknown")) {
DestroyBurFlags |= 0x80000000;
} else if (!_wcsicmp(Argv[i], L"/key")) {
ExpectKey = TRUE;
} else if (!_wcsicmp(Argv[i], L"/spin")) {
Spin = TRUE;
} else if (*Argv[i] == L'/') {
fprintf(stderr, "Don't understand %ws\n", Argv[i]);
exit(1);
}
}
SPIN_ON_INITIALIZE:
WStatus = NtFrsApiInitializeBackupRestore(FrsErrorCallBack,
BurFlags,
&BurContext);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"ERROR NtFrsApiInitializeBackupRestore(%08x) Error %d\n",
BurFlags,
WStatus);
if (Spin) {
Sleep(2 * 1000);
goto SPIN_ON_INITIALIZE;
}
exit(1);
}
WStatus = NtFrsApiGetBackupRestoreSets(BurContext);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"WARN NtFrsApiGetBackupRestoreSets() Error %d\n",
WStatus);
goto DESTROY;
}
BurSetIndex = 0;
while (TRUE) {
WStatus = NtFrsApiEnumBackupRestoreSets(BurContext,
BurSetIndex,
&BurSet);
if (!WIN_SUCCESS(WStatus)) {
break;
}
WStatus = NtFrsApiIsBackupRestoreSetASysvol(BurContext,
BurSet,
&IsSysvol);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"ERROR NtFrsApiIsBackupRestoreSetASysvol(%d) Error %d\n",
BurSetIndex,
WStatus);
goto DESTROY;
}
//
// Directory
//
BufferSize = 1;
WStatus = NtFrsApiGetBackupRestoreSetDirectory(BurContext,
BurSet,
&BufferSize,
Buffer);
if (WStatus != ERROR_INSUFFICIENT_BUFFER) {
fprintf(stderr,
"ERROR NtFrsApiIsBackupRestoreSetASysvol(%d) Error %d\n",
BurSetIndex,
WStatus);
}
BufferSize = 1024;
WStatus = NtFrsApiGetBackupRestoreSetDirectory(BurContext,
BurSet,
&BufferSize,
Buffer);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"ERROR NtFrsApiIsBackupRestoreSetASysvol(%d) Error %d\n",
BurSetIndex,
WStatus);
goto DESTROY;
}
//
// Paths
//
Buffer2Size = 1;
FiltersSize = 1;
WStatus = NtFrsApiGetBackupRestoreSetPaths(BurContext,
BurSet,
&Buffer2Size,
Buffer2,
&FiltersSize,
Filters);
if (WStatus != ERROR_INSUFFICIENT_BUFFER) {
fprintf(stderr,
"ERROR NtFrsApiGetBackupRestorePaths(%d) Error %d\n",
BurSetIndex,
WStatus);
}
Buffer2Size = 1024;
FiltersSize = 1;
WStatus = NtFrsApiGetBackupRestoreSetPaths(BurContext,
BurSet,
&Buffer2Size,
Buffer2,
&FiltersSize,
Filters);
if (WStatus != ERROR_INSUFFICIENT_BUFFER) {
fprintf(stderr,
"ERROR NtFrsApiGetBackupRestorePaths(FILTERS %d) Error %d\n",
BurSetIndex,
WStatus);
}
Buffer2Size = 1024;
FiltersSize = 1024;
WStatus = NtFrsApiGetBackupRestoreSetPaths(BurContext,
BurSet,
&Buffer2Size,
Buffer2,
&FiltersSize,
Filters);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"ERROR NtFrsApiGetBackupRestorePaths(%d) Error %d\n",
BurSetIndex,
WStatus);
goto DESTROY;
}
if (IsSysvol) {
printf("BurSet %d: %ws is a sysvol\n",
BurSetIndex,
Buffer);
} else {
printf("BurSet %d: %ws\n",
BurSetIndex,
Buffer);
}
if (Buffer2Size) {
Str = Buffer2;
while(*Str) {
printf(" Path : %ws\n", Str);
Str += wcslen(Str) + 1;
}
}
if (FiltersSize) {
Str = Filters;
while(*Str) {
printf(" Filter: %ws\n", Str);
Str += wcslen(Str) + 1;
}
}
Dir = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, sizeof(DIRS));
Dir->Dir = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, BufferSize);
CopyMemory(Dir->Dir, Buffer, BufferSize);
Dir->BurSet = BurSet;
Dir->Next = Dirs;
Dirs = Dir;
++BurSetIndex;
}
if (!WIN_SUCCESS(WStatus) && WStatus != ERROR_NO_MORE_ITEMS) {
fprintf(stderr,
"ERROR NtFrsApiEnumBackupRestoreSets(%d) Error %d\n",
BurSetIndex,
WStatus);
goto DESTROY;
}
for (i = 2; i < argc; ++i) {
if (*Argv[i] == L'/') {
continue;
}
DirPath = Argv[i++];
if (i >= argc) {
printf("%ws does not have a corresponding primary|nonauth\n",
DirPath);
continue;
}
DirType = Argv[i];
printf("Processing %ws %ws\n", DirPath, DirType);
if (!_wcsicmp(DirType, L"primary")) {
BurFlags = NTFRSAPI_BUR_FLAGS_PRIMARY;
} else if (!_wcsicmp(DirType, L"nonauth")) {
BurFlags = NTFRSAPI_BUR_FLAGS_NON_AUTHORITATIVE;
} else {
printf("Don't understand %ws\n", DirType);
continue;
}
for (Dir = Dirs; Dir; Dir = Dir->Next) {
if (!_wcsicmp(Dir->Dir, DirPath)) {
break;
}
}
if (!Dir) {
printf("%ws not found\n", DirPath);
continue;
}
WStatus = NtFrsApiRestoringDirectory(BurContext,
Dir->BurSet,
BurFlags);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"ERROR NtFrsApiRestoringDirectory(%ws, %08x) Error %d\n",
DirPath,
BurFlags,
WStatus);
continue;
}
WStatus = NtFrsApiFinishedRestoringDirectory(BurContext,
Dir->BurSet,
NTFRSAPI_BUR_FLAGS_NONE);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"ERROR NtFrsApiFinishedRestoringDirectory(%ws, %08x) Error %d\n",
DirPath,
BurFlags,
WStatus);
continue;
}
printf("Finished restoring %ws\n", DirPath);
}
DESTROY:
if (Spin) {
printf("Spinning...\n");
}
while (Spin) {
Sleep(2 * 1000);
}
BufferSize = 1024;
WStatus = NtFrsApiDestroyBackupRestore(&BurContext,
DestroyBurFlags,
(ExpectKey) ? &HKey : NULL,
(ExpectKey) ? &BufferSize : NULL,
(ExpectKey) ? Buffer : NULL);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr,
"ERROR NtFrsApiDestroyBackupRestore(%08x) Error %d\n",
DestroyBurFlags,
WStatus);
exit(1);
}
if (ExpectKey) {
printf("%08x HKey, %d KeySize, %ws\n", HKey, BufferSize, Buffer);
}
#if 0
WStatus = NtFrsApi_GetReplicatedDirectoriesW(FrsErrorCallBack, &Dirs);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr, "ERROR NtFrsApi_GetReplicatedDirectories() Error %d\n", WStatus);
exit(1);
}
if (Dirs) {
while (*Dirs != L'\0') {
fprintf(stdout, "Dirs:%ws:\n", Dirs);
Dirs = &Dirs[wcslen(Dirs) + 1];
}
LocalFree(Dirs);
}
WStatus = NtFrsApi_StopServiceForFullNonAuthRestoreW(Primary,
FrsErrorCallBack);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr, "ERROR NtFrsApi_StopServiceForFullNonAuth() Error %d\n", WStatus);
exit(1);
}
WStatus = NtFrsApi_StartServiceAfterFullNonAuthRestoreW(FrsErrorCallBack);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr, "ERROR NtFrsApi_StartServiceAfterFullNonAuth() Error %d\n", WStatus);
exit(1);
}
#endif 0
exit(0);
}
VOID
ProcessComm(
IN DWORD argc,
IN PWCHAR *Argv,
IN DWORD CommCommand
)
/*++
Routine Description:
Dump bunches of stuff
Arguments:
argc
Argv
CommCommand
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
DWORD WStatus;
PWCHAR Line;
PWCHAR ComputerName1 = NULL;
PWCHAR ComputerName2 = NULL;
PWCHAR Account = NULL;
PWCHAR Password = NULL;
PVOID Info = NULL;
if (argc > 2) {
ComputerName1 = Argv[2];
if (ComputerName1 && !*ComputerName1) {
ComputerName1 = NULL;
}
}
if (argc > 3) {
ComputerName2 = Argv[3];
if (ComputerName2 && !*ComputerName2) {
ComputerName2 = NULL;
}
}
if (argc > 4) {
Account = Argv[4];
if (Account && !*Account) {
Account = NULL;
}
}
if (argc > 5) {
Password = Argv[5];
if (Password && !*Password) {
Password = NULL;
}
}
#if 0
not yet implemented
WStatus = NtFrsApi_CommW(CommCommand,
ComputerName1,
ComputerName2,
Account,
Password,
&Info);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr, "NtFrsApi_CommW() -> %d\n", WStatus);
exit(1);
}
Line = NULL;
AGAIN:
WStatus = NtFrsApi_InfoLineW(Info, &Line);
if (!WIN_SUCCESS(WStatus)) {
fprintf(stderr, "NtFrsApi_InfoLineW() -> %d\n", WStatus);
exit(1);
}
if (Line) {
printf("%ws", Line);
goto AGAIN;
}
NtFrsApi_Free_InfoW(&Info);
#endif 0
exit(0);
}
#define PRIV_BUF_LENGTH (1024)
VOID
LogOnAsComputer(
)
/*++
Routine Description:
Check if the caller is a member of Groups
Arguments:
ServerHandle
Groups
Return Value:
Win32 Status
--*/
{
#define DEBSUB "CheckGroups:"
DWORD WStatus;
PVOID PrivBuf;
DWORD PrivBufLen;
DWORD LastPrivBufLen;
HANDLE IdHandle;
HANDLE TokenHandle;
DWORD i;
DWORD j;
TOKEN_PRIVILEGES *Tp;
DWORD ComputerLen;
WCHAR ComputerName[MAX_COMPUTERNAME_LENGTH + 1];
DWORD PrivLen;
WCHAR PrivName[MAX_PATH + 1];
ComputerLen = MAX_COMPUTERNAME_LENGTH;
ComputerName[0] = L'\0';
if (!GetComputerName(ComputerName, &ComputerLen)) {
printf("FRS: Cannot get the computer's name\n");
return;
}
printf("Computer name is %ws\n", ComputerName);
//
// For this process
//
IdHandle = GetCurrentProcess();
if (!OpenProcessToken(IdHandle, TOKEN_QUERY, &TokenHandle)) {
WStatus = GetLastError();
printf("Can't open process token; WStatus %d\n", WStatus);
goto cleanup;
}
//
// Get the groups from the access token for this thread or process
//
PrivBufLen = PRIV_BUF_LENGTH;
do {
PrivBuf = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, PrivBufLen);
LastPrivBufLen = PrivBufLen;
if (!GetTokenInformation(TokenHandle,
TokenPrivileges,
PrivBuf,
PrivBufLen,
&PrivBufLen)) {
WStatus = GetLastError();
printf("Can't get privs groups; WStatus %d (lastlen %d; curlen %d\n",
WStatus,
LastPrivBufLen,
PrivBufLen);
FREE(PrivBuf);
} else {
WStatus = ERROR_SUCCESS;
}
} while (!WIN_SUCCESS(WStatus) && LastPrivBufLen < PrivBufLen);
if (!WIN_SUCCESS(WStatus)) {
goto cleanup;
}
Tp = (TOKEN_PRIVILEGES *)PrivBuf;
for (i = 0; i < Tp->PrivilegeCount; ++i) {
PrivLen = MAX_PATH + 1;
if (!LookupPrivilegeName(NULL,
&Tp->Privileges[i].Luid,
PrivName,
&PrivLen)) {
printf("lookuppriv error %d\n", GetLastError());
exit(0);
}
printf("Priv %d is %ws\n", i, PrivName);
}
printf("Okay\n");
CloseHandle(TokenHandle);
if (!LogonUser(L"Administrator",
NULL,
NULL,
LOGON32_LOGON_SERVICE,
LOGON32_PROVIDER_DEFAULT,
&TokenHandle)) {
printf("ERROR - %d logon\n", GetLastError());
exit(0);
}
cleanup:
CloseHandle(TokenHandle);
CloseHandle(IdHandle);
FREE(PrivBuf);
}
// --------------- Process Install Stage
BOOL
FrsSetCompression(
IN PWCHAR Path,
IN HANDLE Handle,
IN USHORT TypeOfCompression
)
/*++
Routine Description:
Enable compression on Handle.
Arguments:
Path
Handle
TypeOfCompression
Return Value:
Set the compression mode on a file
--*/
{
DWORD BytesReturned;
if (!DeviceIoControl(Handle,
FSCTL_SET_COMPRESSION,
&TypeOfCompression,
sizeof(TypeOfCompression),
NULL,
0,
&BytesReturned,
NULL)) {
Win32ToMsg(Path, GetLastError());
return FALSE;
}
return TRUE;
}
BOOL
FrsSetFileAttributes(
PWCHAR Path,
HANDLE Handle,
ULONG FileAttributes
)
/*++
Routine Description:
This routine sets the file's attributes
Arguments:
Path - for error messages
Handle - Supplies a handle to the file that is to be marked for delete.
Attributes - Attributes for the file
Return Value:
TRUE - attributes have been set
FALSE
--*/
{
IO_STATUS_BLOCK IoStatus;
FILE_BASIC_INFORMATION BasicInformation;
NTSTATUS Status;
//
// Set the attributes
//
ZeroMemory(&BasicInformation, sizeof(BasicInformation));
BasicInformation.FileAttributes = FileAttributes | FILE_ATTRIBUTE_NORMAL;
Status = NtSetInformationFile(Handle,
&IoStatus,
&BasicInformation,
sizeof(BasicInformation),
FileBasicInformation);
if (!NT_SUCCESS(Status)) {
fprintf(stderr, "NtSetFileInformationFile(%ws); NtStatus 0x%08x\n",
Path,
Status);
return FALSE;
}
return TRUE;
}
DWORD
FrsSetFilePointer(
IN PWCHAR Name,
IN HANDLE Handle,
IN ULONG High,
IN ULONG Low
)
/*++
Routine Description:
Position file pointer
Arguments:
Handle
Name
High
Low
Return Value:
Win32 Error Status
--*/
{
#undef DEBSUB
#define DEBSUB "FrsSetFilePointer:"
DWORD WStatus;
Low = SetFilePointer(Handle, Low, &High, FILE_BEGIN);
if (Low == INVALID_SET_FILE_POINTER) {
WStatus = GetLastError();
if (WStatus != NO_ERROR) {
Win32ToMsg(Name, WStatus);
return WStatus;
}
}
return ERROR_SUCCESS;
}
BOOL
StuReadFile(
IN PWCHAR Path,
IN HANDLE Handle,
IN PVOID Buf,
IN DWORD BytesToRead,
OUT PDWORD BytesRead
)
/*++
Routine Description:
Read data from a file
Arguments:
Path
Handle
Buf
BytesToRead
Return Value:
TRUE - no problem
FALSE - couldn't read
--*/
{
BOOL DidRead;
//
// Read the file's name into the file
//
DidRead = ReadFile(Handle, Buf, BytesToRead, BytesRead, NULL);
//
// Read error
//
if (!DidRead) {
Win32ToMsg(Path, GetLastError());
return FALSE;
}
//
// Done
//
return TRUE;
}
BOOL
FrsSetFileTime(
IN PWCHAR Path,
IN HANDLE Handle,
IN FILETIME *CreateTime,
IN FILETIME *AccessTime,
IN FILETIME *WriteTime
)
/*++
Routine Description:
Position file pointer
Arguments:
Path
Handle
Attributes
CreateTime
AccessTime
WriteTime
Return Value:
TRUE - no problem
FALSE - couldn't set size
--*/
{
if (!SetFileTime(Handle, CreateTime, AccessTime, WriteTime)) {
Win32ToMsg(Path, GetLastError());
return FALSE;
}
return TRUE;
}
#define IOSIZE (64 * 1024)
VOID
ProcessInstall(
IN DWORD argc,
IN PWCHAR *Argv
)
/*++
Routine Description:
Restore the StagePath to TargetPath if TargetPath is non-NULL.
Arguments:
argc - number of argv's
Argv - stagepath and, optionally, targetpath
Return Value:
Win32 status
--*/
{
BOOL IsDir;
BOOL ExistingOid;
ULONG High;
ULONG Low;
ULONG WStatus;
ULONG Restored;
ULONG ToRestore;
ULONG FileOffset;
PUCHAR RestoreBuf = NULL;
PVOID RestoreContext = NULL;
DWORD BytesRead = 0;
HANDLE StageHandle = INVALID_HANDLE_VALUE;
PWCHAR StagePath = NULL;
PWCHAR TargetPath = NULL;
HANDLE TargetHandle = INVALID_HANDLE_VALUE;
STAGE_HEADER Header;
WIN32_STREAM_ID *StreamId = NULL;
DWORD RestoreStreamOffset = 0;
#if 0
typedef struct _WIN32_STREAM_ID {
DWORD dwStreamId ;
DWORD dwStreamAttributes ;
LARGE_INTEGER Size ;
DWORD dwStreamNameSize ;
WCHAR cStreamName[ ANYSIZE_ARRAY ] ;
} WIN32_STREAM_ID, *LPWIN32_STREAM_ID ;
#endif 0
//
// Check params
//
if (argc < 3 || argc > 4) {
Usage(1);
}
StagePath = Argv[2];
if (argc == 4) {
TargetPath = Argv[3];
}
printf("%ws %ws %ws %ws\n",
Argv[0],
Argv[1],
Argv[2],
(argc == 4) ? Argv[3] : L"");
//
// Open the stage file for shared, sequential reads
//
//
// Open the file
//
printf("Stage path: %ws\n", StagePath);
StageHandle = CreateFile(StagePath,
GENERIC_READ,
FILE_SHARE_READ,
NULL,
OPEN_EXISTING,
FILE_FLAG_SEQUENTIAL_SCAN |
FILE_FLAG_BACKUP_SEMANTICS,
NULL);
if (StageHandle == INVALID_HANDLE_VALUE) {
Win32ToMsg(StagePath, GetLastError());
Win32ToMsg(L"CreateFile(StagePath)", GetLastError());
goto CLEANUP;
}
//
// Read the header
//
if (!ReadFile(StageHandle,
&Header,
sizeof(STAGE_HEADER),
&BytesRead,
NULL)) {
Win32ToMsg(StagePath, GetLastError());
goto CLEANUP;
}
if (BytesRead != sizeof(STAGE_HEADER)) {
fprintf(stderr, "%ws: Read %d bytes, not %d\n",
StagePath,
BytesRead,
sizeof(STAGE_HEADER));
goto CLEANUP;
}
printf("Stage Header:\n");
printf("\tName : %ws\n", Header.ChangeOrderCommand.FileName);
printf("\tMajor : %08x\n", Header.Major);
printf("\tMinor : %08x\n", Header.Minor);
printf("\tDataHigh : %08x\n", Header.DataHigh);
printf("\tDataLow : %08x\n", Header.DataLow);
printf("\tCompression: %08x\n", Header.Compression);
printf("\tAttributes : %08x\n", Header.Attributes.FileAttributes);
//
// Don't understand this header format
//
if (Header.Major != NTFRS_MAJOR) {
fprintf(stderr, "%ws: Major %d != NtFrsMajor %d\n",
StagePath,
Header.Major,
NTFRS_MAJOR);
goto CLEANUP;
}
if (!TargetPath) {
goto CLEANUP;
}
//
// INSTALL STAGE FILE
//
//
// Open the file
//
printf("Target path: %ws\n", TargetPath);
IsDir = Header.Attributes.FileAttributes & FILE_ATTRIBUTE_DIRECTORY;
TargetHandle = CreateFile(TargetPath,
RESTORE_ACCESS,
0,
NULL,
OPEN_ALWAYS,
OPEN_OPTIONS,
NULL);
if (TargetHandle == INVALID_HANDLE_VALUE) {
Win32ToMsg(TargetPath, GetLastError());
Win32ToMsg(L"CreateFile(TargetPath)", GetLastError());
goto CLEANUP;
}
//
// Truncate the file if not a directory
//
if (!IsDir && !SetEndOfFile(TargetHandle)) {
Win32ToMsg(TargetPath, GetLastError());
goto CLEANUP;
}
//
// Set compression mode
//
if (!FrsSetCompression(TargetPath,
TargetHandle,
Header.Compression)) {
goto CLEANUP;
}
//
// Set attributes
//
if (!FrsSetFileAttributes(TargetPath,
TargetHandle,
Header.Attributes.FileAttributes &
~NOREPL_ATTRIBUTES)) {
goto CLEANUP;
}
//
// Seek to the first byte of data in the stage file
//
if (FrsSetFilePointer(StagePath,
StageHandle,
Header.DataHigh,
Header.DataLow) != ERROR_SUCCESS) {
goto CLEANUP;
}
FileOffset = Header.DataLow;
//
// Restore the stage file into the temporary file
//
RestoreBuf = LocalAlloc(LMEM_FIXED | LMEM_ZEROINIT, IOSIZE);
do {
//
// read stage
//
printf("Reading %d bytes at %08x\n", IOSIZE, FileOffset);
if (!StuReadFile(StagePath,
StageHandle,
RestoreBuf,
IOSIZE,
&ToRestore)) {
goto CLEANUP;
}
printf("Read %d bytes at %08x\n", ToRestore, FileOffset);
FileOffset += ToRestore;
if (ToRestore == 0) {
break;
}
//
// Dump stream heads in first restore buffer
// Increase buffer size to catch all heads OR
// enhance code to remember stream head offsets
// across restore bufs.
//
if (StreamId == NULL) {
RestoreStreamOffset = 0;
while (RestoreStreamOffset < ToRestore) {
StreamId = (WIN32_STREAM_ID *)(RestoreBuf + RestoreStreamOffset);
printf("StreamId: %08x %d (%08x)\n", StreamId, RestoreStreamOffset);
printf("dwStreamId: %d\n", StreamId->dwStreamId);
printf("dwStreamAttributes: %08x\n", StreamId->dwStreamAttributes);
printf("Size High: %08x\n", StreamId->Size.HighPart);
printf("Size Low: %08x\n", StreamId->Size.LowPart);
printf("dwStreamNameSize: %d\n", StreamId->dwStreamNameSize);
RestoreStreamOffset += (sizeof(WIN32_STREAM_ID) - 4);
RestoreStreamOffset += StreamId->dwStreamNameSize;
RestoreStreamOffset += StreamId->Size.LowPart;
}
}
if (!BackupWrite(TargetHandle,
RestoreBuf,
ToRestore,
&Restored,
FALSE,
TRUE,
&RestoreContext)) {
WStatus = GetLastError();
printf("BackupWrite(%08x, %d) returned %d\n",
RestoreContext,
ToRestore,
WStatus);
if (IsDir && WStatus == ERROR_ALREADY_EXISTS) {
fprintf(stderr, "%ws: WStatus %d IGNORED; dirs and altstreams\n",
TargetPath,
WStatus);
}
//
// Uknown stream header or couldn't apply object id
//
if (WStatus == ERROR_INVALID_DATA ||
WStatus == ERROR_DUP_NAME ||
(IsDir && WStatus == ERROR_ALREADY_EXISTS)) {
//
// Seek to the next stream. Stop if there are none.
//
printf("BackupWrite() returned %d; try to seek past bad data\n", WStatus);
BackupSeek(TargetHandle,
-1,
-1,
&Low,
&High,
&RestoreContext);
if (Low == 0 && High == 0) {
printf("BackupSeek failed; abort\n");
break;
}
fprintf(stderr, "%ws: WStatus %d IGNORED; BackupSeek() okay\n",
TargetPath,
WStatus);
} else {
//
// Unknown error; abort
//
Win32ToMsg(TargetPath, GetLastError());
goto CLEANUP;
}
} else {
printf("BackupWrite(%08x, %d) okay\n", RestoreContext, ToRestore);
}
} while (TRUE);
#if 0
//
// Insure the correct object ID is on the file.
//
FRS_ASSERT(!memcmp(Header->FileObjId.ObjectId, &Coc->FileGuid, sizeof(GUID)));
bugbug("do we have to write the extend OID data here???")
WStatus = FrsGetOrSetFileObjectId(DstHandle,
Coc->FileName,
TRUE,
&Header->FileObjId);
if (WStatus == ERROR_DUP_NAME) {
DPRINT2(0, "Stealing object id for %ws; WStatus %d\n",
Coc->FileName,
WStatus);
ZeroMemory(&FileObjID, sizeof(FileObjID));
FrsUuidCreate((GUID *)(&FileObjID.ObjectId[0]));
ExistingOid = FALSE;
WStatus = ChgOrdHammerObjectId(Coc->FileName,
&Coc->FileGuid,
OBJECT_ID_LENGTH,
Coc->NewReplica->pVme,
TRUE,
NULL,
&FileObjID,
&ExistingOid);
if (WIN_SUCCESS(WStatus)) {
WStatus = FrsGetOrSetFileObjectId(DstHandle,
Coc->FileName,
TRUE,
&Header->FileObjId);
}
if (!WIN_SUCCESS(WStatus)) {
DPRINT2(0, "Retry install of %ws because of object id; WStatus %d\n",
Coc->FileName,
WStatus);
WStatus = ERROR_RETRY;
}
}
if (!WIN_SUCCESS(WStatus)) {
goto out;
}
#endif 0
//
// Set times
//
if (!FrsSetFileTime(TargetPath,
TargetHandle,
(PFILETIME)&Header.Attributes.CreationTime.QuadPart,
(PFILETIME)&Header.Attributes.LastAccessTime.QuadPart,
(PFILETIME)&Header.Attributes.LastWriteTime.QuadPart)) {
goto CLEANUP;
}
//
// Set final attributes
//
if (!FrsSetFileAttributes(TargetPath,
TargetHandle,
Header.Attributes.FileAttributes)) {
goto CLEANUP;
}
//
// Make sure all of the data is on disk. We don't want to lose
// it across reboots
//
if (!FlushFileBuffers(TargetHandle)) {
Win32ToMsg(TargetPath, GetLastError());
goto CLEANUP;
}
CLEANUP:
//
// Free up the restore context before we close TmpHandle (just in case)
//
if (RestoreContext) {
printf("Discard BackupWrite(%08x)\n", RestoreContext);
BackupWrite(TargetHandle,
NULL,
0,
NULL,
TRUE,
TRUE,
&RestoreContext);
}
if (StageHandle && StageHandle != INVALID_HANDLE_VALUE) {
CloseHandle(StageHandle);
}
if (TargetHandle && TargetHandle != INVALID_HANDLE_VALUE) {
CloseHandle(TargetHandle);
}
FREE(RestoreBuf);
printf("Install of %ws into %ws complete\n",
StagePath,
TargetPath);
}
// ----------------
VOID _cdecl
main(
IN DWORD argc,
IN PCHAR *argv
)
/*++
Routine Description:
Process the command line.
Arguments:
argc
argv
Return Value:
Exits with 0 if everything went okay. Otherwise, 1.
--*/
{
PWCHAR *Argv;
//
// Print usage and exit
//
if (argc == 1) {
Usage(0);
}
//
// Use wide char parameters
//
Argv = ConvertArgv(argc, argv);
//
// Find the subcommand
//
if (!wcscmp(Argv[1], L"poll")) {
ProcessPoll(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"promote")) {
ProcessPromote(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"promoteabort")) {
ProcessPromoteAbort(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"promotesysvols")) {
ProcessPromoteSysVols(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"demote")) {
ProcessDemote(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"demoteabort")) {
ProcessDemoteAbort(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"demotesysvols")) {
ProcessDemoteSysVols(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"version")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_VERSION);
} else if (!_wcsicmp(Argv[1], L"sets")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_SETS);
} else if (!_wcsicmp(Argv[1], L"ds")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_DS);
} else if (!_wcsicmp(Argv[1], L"memory")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_MEMORY);
} else if (!_wcsicmp(Argv[1], L"idtable")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_IDTABLE);
} else if (!_wcsicmp(Argv[1], L"inlog")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_INLOG);
} else if (!_wcsicmp(Argv[1], L"outlog")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_OUTLOG);
} else if (!_wcsicmp(Argv[1], L"threads")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_THREADS);
} else if (!_wcsicmp(Argv[1], L"stage")) {
ProcessDump(argc, Argv, NTFRSAPI_INFO_TYPE_STAGE);
} else if (!_wcsicmp(Argv[1], L"install")) {
ProcessInstall(argc, Argv);
} else if (!_wcsicmp(Argv[1], L"restore")) {
ProcessBackupRestore(argc, Argv, NTFRSAPI_BUR_FLAGS_RESTORE);
} else if (!_wcsicmp(Argv[1], L"backup")) {
ProcessBackupRestore(argc, Argv, NTFRSAPI_BUR_FLAGS_BACKUP);
} else if (!_wcsicmp(Argv[1], L"comm")) {
// Not implemented
// ProcessComm(argc, Argv, NTFRSAPI_COMM_COMMAND_TEST);
} else {
fprintf(stderr, "Don't understand %ws\n", Argv[1]);
Usage(1);
}
exit(0);
}