915 lines
19 KiB
C
915 lines
19 KiB
C
#include "precomp.h"
|
|
|
|
#define MALLOC(x) HeapAlloc(GetProcessHeap(), 0, (x))
|
|
#define FREE(x) HeapFree(GetProcessHeap(), 0, (x))
|
|
|
|
DWORD
|
|
HandleShowAlias(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
return PrintAliasTable();
|
|
}
|
|
|
|
DWORD
|
|
HandleShellExit(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
BOOL bTmp;
|
|
|
|
CallCommit(NETSH_COMMIT_STATE, &bTmp);
|
|
|
|
if (!bTmp)
|
|
{
|
|
CallCommit(NETSH_FLUSH, &bTmp);
|
|
}
|
|
|
|
*pbDone = TRUE;
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellLoad(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
DWORD dwErr, dwNumArgs;
|
|
|
|
dwNumArgs = dwArgCount - dwCurrentIndex;
|
|
|
|
//
|
|
// Load Command
|
|
//
|
|
switch (dwNumArgs)
|
|
{
|
|
case 1 :
|
|
return LoadScriptFile(ppwcArguments[dwCurrentIndex]);
|
|
|
|
default :
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellSave(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
BOOL bTmp;
|
|
|
|
CallCommit(NETSH_SAVE, &bTmp);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellUncommit(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
BOOL bTmp;
|
|
|
|
CallCommit(NETSH_UNCOMMIT, &bTmp);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleSetMachine(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
TAG_TYPE pttTags[] = {{TOKEN_NAME, FALSE, FALSE }};
|
|
DWORD dwNumTags = sizeof(pttTags)/sizeof(TAG_TYPE);
|
|
PDWORD pdwTagType;
|
|
DWORD dwErr, dwNumArg, dwMode, i;
|
|
BOOL bTmp;
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
if (dwNumArg < 1)
|
|
{
|
|
return SetMachine(NULL);
|
|
}
|
|
|
|
if (dwNumArg < 1)
|
|
{
|
|
return SetMachine(NULL);
|
|
}
|
|
|
|
if ((dwNumArg != 1) || IsHelpToken(ppwcArguments[dwCurrentIndex]))
|
|
{
|
|
return ERROR_SHOW_USAGE;
|
|
}
|
|
|
|
pdwTagType = MALLOC(dwNumArg * sizeof(DWORD));
|
|
|
|
if (pdwTagType is NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
dwErr = MatchTagsInCmdLine(g_hModule,
|
|
ppwcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
pttTags,
|
|
dwNumTags,
|
|
pdwTagType);
|
|
|
|
if (dwErr isnot NO_ERROR)
|
|
{
|
|
FREE(pdwTagType);
|
|
if (dwErr is ERROR_INVALID_OPTION_TAG)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
return dwErr;
|
|
}
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0: // NAME
|
|
{
|
|
SetMachine(ppwcArguments[i + dwCurrentIndex]);
|
|
|
|
break;
|
|
}
|
|
|
|
default :
|
|
{
|
|
i = dwNumArg;
|
|
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FREE(pdwTagType);
|
|
|
|
switch(dwErr)
|
|
{
|
|
case NO_ERROR :
|
|
break;
|
|
|
|
case ERROR_TAG_ALREADY_PRESENT:
|
|
PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT);
|
|
return dwErr;
|
|
|
|
default:
|
|
return dwErr;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
extern HANDLE g_hLogFile;
|
|
|
|
DWORD
|
|
HandleSetFile(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
TAG_TYPE pttTags[] = {
|
|
{TOKEN_MODE, TRUE, FALSE },
|
|
{TOKEN_NAME, FALSE, FALSE },
|
|
};
|
|
DWORD dwNumTags = sizeof(pttTags)/sizeof(TAG_TYPE);
|
|
PDWORD pdwTagType;
|
|
DWORD dwErr, dwNumArg, dwMode, i;
|
|
BOOL bTmp;
|
|
LPCWSTR wszFileName = NULL;
|
|
HANDLE hLogFile = NULL;
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
if ((!dwNumArg) || (dwNumArg > 2) || IsHelpToken(ppwcArguments[dwCurrentIndex]))
|
|
{
|
|
return ERROR_SHOW_USAGE;
|
|
}
|
|
|
|
pdwTagType = MALLOC(dwNumArg * sizeof(DWORD));
|
|
|
|
if (pdwTagType is NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
dwErr = MatchTagsInCmdLine(g_hModule,
|
|
ppwcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
pttTags,
|
|
dwNumTags,
|
|
pdwTagType);
|
|
|
|
if (dwErr isnot NO_ERROR)
|
|
{
|
|
FREE(pdwTagType);
|
|
if (dwErr is ERROR_INVALID_OPTION_TAG)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
return dwErr;
|
|
}
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0: // Mode
|
|
{
|
|
TOKEN_VALUE rgEnums[] = {{TOKEN_VALUE_OPEN, 0},
|
|
{TOKEN_VALUE_APPEND, 1},
|
|
{TOKEN_VALUE_CLOSE, 2}};
|
|
|
|
dwErr = MatchEnumTag(g_hModule,
|
|
ppwcArguments[i + dwCurrentIndex],
|
|
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
|
|
rgEnums,
|
|
&dwMode);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessageFromModule( g_hModule,
|
|
ERROR_INVALID_OPTION_VALUE,
|
|
pttTags[pdwTagType[i]].pwszTag,
|
|
ppwcArguments[i + dwCurrentIndex]);
|
|
|
|
i = dwNumArg;
|
|
|
|
dwErr = ERROR_SHOW_USAGE;
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
case 1: // Name
|
|
{
|
|
wszFileName = ppwcArguments[i + dwCurrentIndex];
|
|
break;
|
|
}
|
|
default :
|
|
{
|
|
i = dwNumArg;
|
|
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
FREE(pdwTagType);
|
|
switch(dwErr)
|
|
{
|
|
case NO_ERROR :
|
|
break;
|
|
|
|
case ERROR_TAG_ALREADY_PRESENT:
|
|
PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT);
|
|
return dwErr;
|
|
|
|
default:
|
|
return dwErr;
|
|
}
|
|
|
|
switch(dwMode)
|
|
{
|
|
case 0: // open
|
|
if (!wszFileName)
|
|
return ERROR_SHOW_USAGE;
|
|
|
|
if (g_hLogFile)
|
|
{
|
|
CloseHandle(g_hLogFile);
|
|
g_hLogFile = NULL;
|
|
}
|
|
|
|
hLogFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, CREATE_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (INVALID_HANDLE_VALUE == hLogFile)
|
|
return GetLastError();
|
|
|
|
g_hLogFile = hLogFile;
|
|
break;
|
|
|
|
case 1: // append
|
|
if (!wszFileName)
|
|
return ERROR_SHOW_USAGE;
|
|
|
|
if (g_hLogFile)
|
|
{
|
|
CloseHandle(g_hLogFile);
|
|
g_hLogFile = NULL;
|
|
}
|
|
|
|
hLogFile = CreateFile(wszFileName, GENERIC_WRITE, FILE_SHARE_READ, NULL, OPEN_ALWAYS, FILE_ATTRIBUTE_NORMAL, NULL);
|
|
if (INVALID_HANDLE_VALUE == hLogFile)
|
|
return GetLastError();
|
|
|
|
if (INVALID_SET_FILE_POINTER == SetFilePointer(hLogFile, 0, NULL, FILE_END))
|
|
return GetLastError();
|
|
|
|
g_hLogFile = hLogFile;
|
|
|
|
break;
|
|
|
|
case 2: // close
|
|
if (wszFileName)
|
|
return ERROR_SHOW_USAGE;
|
|
|
|
if (g_hLogFile)
|
|
{
|
|
CloseHandle(g_hLogFile);
|
|
g_hLogFile = NULL;
|
|
}
|
|
break;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
|
|
DWORD
|
|
HandleSetMode(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
TAG_TYPE pttTags[] = {{TOKEN_MODE, TRUE, FALSE }};
|
|
DWORD dwNumTags = sizeof(pttTags)/sizeof(TAG_TYPE);
|
|
PDWORD pdwTagType;
|
|
DWORD dwErr, dwNumArg, dwMode, i;
|
|
BOOL bTmp;
|
|
|
|
dwNumArg = dwArgCount - dwCurrentIndex;
|
|
|
|
if ((dwNumArg != 1) || IsHelpToken(ppwcArguments[dwCurrentIndex]))
|
|
{
|
|
return ERROR_SHOW_USAGE;
|
|
}
|
|
|
|
pdwTagType = MALLOC(dwNumArg * sizeof(DWORD));
|
|
|
|
if (pdwTagType is NULL)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
dwErr = MatchTagsInCmdLine(g_hModule,
|
|
ppwcArguments,
|
|
dwCurrentIndex,
|
|
dwArgCount,
|
|
pttTags,
|
|
dwNumTags,
|
|
pdwTagType);
|
|
|
|
if (dwErr isnot NO_ERROR)
|
|
{
|
|
FREE(pdwTagType);
|
|
if (dwErr is ERROR_INVALID_OPTION_TAG)
|
|
{
|
|
return ERROR_INVALID_SYNTAX;
|
|
}
|
|
return dwErr;
|
|
}
|
|
|
|
for ( i = 0; i < dwNumArg; i++)
|
|
{
|
|
switch (pdwTagType[i])
|
|
{
|
|
case 0: // LOGLEVEL
|
|
{
|
|
TOKEN_VALUE rgEnums[] = {{TOKEN_VALUE_ONLINE, TRUE},
|
|
{TOKEN_VALUE_OFFLINE, FALSE}};
|
|
|
|
dwErr = MatchEnumTag(g_hModule,
|
|
ppwcArguments[i + dwCurrentIndex],
|
|
sizeof(rgEnums)/sizeof(TOKEN_VALUE),
|
|
rgEnums,
|
|
&dwMode);
|
|
|
|
if (dwErr != NO_ERROR)
|
|
{
|
|
PrintMessageFromModule( g_hModule,
|
|
ERROR_INVALID_OPTION_VALUE,
|
|
pttTags[pdwTagType[i]].pwszTag,
|
|
ppwcArguments[i + dwCurrentIndex]);
|
|
|
|
i = dwNumArg;
|
|
|
|
dwErr = ERROR_INVALID_PARAMETER;
|
|
|
|
break;
|
|
}
|
|
|
|
break;
|
|
}
|
|
|
|
default :
|
|
{
|
|
i = dwNumArg;
|
|
|
|
dwErr = ERROR_INVALID_SYNTAX;
|
|
|
|
break;
|
|
}
|
|
}
|
|
}
|
|
|
|
|
|
FREE(pdwTagType);
|
|
|
|
switch(dwErr)
|
|
{
|
|
case NO_ERROR :
|
|
break;
|
|
|
|
case ERROR_TAG_ALREADY_PRESENT:
|
|
PrintMessageFromModule(g_hModule, ERROR_TAG_ALREADY_PRESENT);
|
|
return dwErr;
|
|
|
|
default:
|
|
return dwErr;
|
|
}
|
|
|
|
switch(dwMode) {
|
|
case TRUE: // set to online
|
|
dwErr = CallCommit(NETSH_COMMIT, &bTmp);
|
|
break;
|
|
|
|
case FALSE: // set to offline
|
|
dwErr = CallCommit(NETSH_UNCOMMIT, &bTmp);
|
|
break;
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellCommit(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
BOOL bTmp;
|
|
|
|
CallCommit(NETSH_COMMIT, &bTmp);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellFlush(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
BOOL bTmp;
|
|
|
|
CallCommit(NETSH_FLUSH, &bTmp);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellUnalias(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
DWORD dwNumArgs;
|
|
DWORD dwRes = NO_ERROR;
|
|
|
|
dwNumArgs = dwArgCount - dwCurrentIndex;
|
|
|
|
//
|
|
// Unalias Command
|
|
//
|
|
|
|
switch (dwNumArgs)
|
|
{
|
|
case 1 :
|
|
|
|
dwRes = ATDeleteAlias(ppwcArguments[dwCurrentIndex]);
|
|
|
|
if (dwRes is NO_ERROR)
|
|
{
|
|
dwRes = ERROR_OKAY;
|
|
break;
|
|
}
|
|
|
|
PrintMessageFromModule(g_hModule, MSG_ALIAS_NOT_FOUND, ppwcArguments[dwCurrentIndex]);
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
dwRes = ERROR_INVALID_SYNTAX;
|
|
break;
|
|
|
|
}
|
|
|
|
return dwRes;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellAlias(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
LPWSTR pwszAliasString;
|
|
WCHAR wszAliasString[MAX_CMD_LEN];
|
|
DWORD i, dwNumArgs, dwRes = NO_ERROR;
|
|
|
|
dwNumArgs = dwArgCount - dwCurrentIndex;
|
|
|
|
//
|
|
// An alias command
|
|
//
|
|
switch (dwNumArgs)
|
|
{
|
|
case 0 :
|
|
//
|
|
// Display all aliases in use
|
|
//
|
|
PrintAliasTable();
|
|
|
|
break;
|
|
|
|
case 1 :
|
|
//
|
|
// Display string for given alias
|
|
//
|
|
|
|
ATLookupAliasTable(ppwcArguments[dwCurrentIndex], &pwszAliasString);
|
|
|
|
if (pwszAliasString)
|
|
{
|
|
PrintMessage(L"%1!s!\n",pwszAliasString);
|
|
}
|
|
else
|
|
{
|
|
PrintMessageFromModule( g_hModule,
|
|
MSG_ALIAS_NOT_FOUND,
|
|
ppwcArguments[dwCurrentIndex] );
|
|
}
|
|
|
|
break;
|
|
|
|
default :
|
|
|
|
//
|
|
// Set alias
|
|
//
|
|
|
|
if (IsLocalCommand(ppwcArguments[dwCurrentIndex], 0))
|
|
{
|
|
PrintMessageFromModule(g_hModule, EMSG_ALIASING_KEYWORD);
|
|
break;
|
|
}
|
|
|
|
wszAliasString[0] = L'\0';
|
|
|
|
for ( i = dwCurrentIndex+1 ; i < dwArgCount ; i++)
|
|
{
|
|
wcscat(wszAliasString, ppwcArguments[i]);
|
|
wcscat(wszAliasString,L" ");
|
|
}
|
|
|
|
wszAliasString[wcslen(wszAliasString)-1] = L'\0';
|
|
|
|
dwRes = ATAddAlias(ppwcArguments[dwCurrentIndex], wszAliasString);
|
|
|
|
if (dwRes is NO_ERROR)
|
|
{
|
|
dwRes = ERROR_OKAY;
|
|
break;
|
|
}
|
|
|
|
//
|
|
// Error in set alias
|
|
//
|
|
|
|
PrintMessageFromModule(g_hModule, MSG_CMD_FAILED);
|
|
|
|
break;
|
|
}
|
|
|
|
return dwRes;
|
|
}
|
|
|
|
DWORD
|
|
HandleUbiqDump(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
DWORD dwErr = NO_ERROR;
|
|
PNS_HELPER_TABLE_ENTRY pHelper;
|
|
|
|
//
|
|
// Dump Command
|
|
//
|
|
|
|
do {
|
|
dwErr = DumpContext( g_CurrentContext,
|
|
ppwcArguments,
|
|
dwArgCount,
|
|
pvData);
|
|
|
|
} while (FALSE);
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
HandleUbiqHelp(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
DWORD dwDisplayFlags = CMD_FLAG_PRIVATE;
|
|
|
|
if (g_bInteractive)
|
|
{
|
|
dwDisplayFlags |= CMD_FLAG_INTERACTIVE;
|
|
}
|
|
|
|
return DisplayContextHelp( g_CurrentContext,
|
|
dwDisplayFlags,
|
|
dwFlags,
|
|
dwArgCount-2+1,
|
|
NULL );
|
|
}
|
|
|
|
DWORD
|
|
HandleShowMode(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
BOOL bTmp;
|
|
|
|
CallCommit(NETSH_COMMIT_STATE, &bTmp);
|
|
|
|
if (bTmp)
|
|
{
|
|
PrintMessage(CMD_COMMIT);
|
|
}
|
|
else
|
|
{
|
|
PrintMessage(CMD_UNCOMMIT);
|
|
}
|
|
PrintMessage(MSG_NEWLINE);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellUplevel(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
DWORD dwRes;
|
|
PLIST_ENTRY pleHead, ple;
|
|
PARG_ENTRY pae;
|
|
|
|
// Convert current context to list
|
|
dwRes = ConvertBufferToArgList(&pleHead, g_pwszContext);
|
|
if (dwRes isnot NO_ERROR)
|
|
{
|
|
return dwRes;
|
|
}
|
|
|
|
// Remove last element if more than two
|
|
if (!IsListEmpty(pleHead) and (pleHead->Flink->Flink isnot pleHead))
|
|
{
|
|
// Delete the last element of the context list
|
|
// (Try inheriting a command from one level up)
|
|
|
|
ple = pleHead->Blink;
|
|
pae = CONTAINING_RECORD(ple, ARG_ENTRY, le);
|
|
if (pae->pwszArg)
|
|
FREE(pae->pwszArg);
|
|
RemoveEntryList(ple);
|
|
FREE(pae);
|
|
}
|
|
|
|
// Convert back to buffer
|
|
dwRes = ConvertArgListToBuffer(pleHead, g_pwszContext);
|
|
|
|
FREE_ARG_LIST(pleHead);
|
|
|
|
return NO_ERROR;
|
|
}
|
|
|
|
typedef struct {
|
|
LIST_ENTRY le;
|
|
WCHAR wszBuffer[MAX_CMD_LEN];
|
|
} CONTEXT_BUFFER, *PCONTEXT_BUFFER;
|
|
|
|
LIST_ENTRY leContextStackHead;
|
|
BOOL bContextStackInit = FALSE;
|
|
|
|
VOID
|
|
InitContextStack()
|
|
{
|
|
if (bContextStackInit)
|
|
return;
|
|
|
|
bContextStackInit = TRUE;
|
|
|
|
InitializeListHead(&leContextStackHead);
|
|
}
|
|
|
|
DWORD
|
|
HandleShellPushd(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
PCONTEXT_BUFFER pcb;
|
|
DWORD dwErr = NO_ERROR;
|
|
|
|
InitContextStack();
|
|
|
|
// Malloc another buffer
|
|
pcb = MALLOC(sizeof(CONTEXT_BUFFER));
|
|
if (!pcb)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
wcscpy(pcb->wszBuffer, g_pwszContext);
|
|
|
|
// Push buffer on stack
|
|
InsertHeadList(&leContextStackHead, &pcb->le);
|
|
|
|
if (dwArgCount > dwCurrentIndex)
|
|
{
|
|
LPWSTR pwszBuffer;
|
|
|
|
// execute the rest of the arguments as a new command
|
|
|
|
// Copy arg array to a buffer
|
|
ConvertArgArrayToBuffer( dwArgCount - dwCurrentIndex,
|
|
ppwcArguments + dwCurrentIndex,
|
|
&pwszBuffer );
|
|
|
|
if (!pwszBuffer)
|
|
{
|
|
return ERROR_NOT_ENOUGH_MEMORY;
|
|
}
|
|
|
|
dwErr = ProcessCommand(pwszBuffer, pbDone);
|
|
if (dwErr)
|
|
{
|
|
dwErr = ERROR_SUPPRESS_OUTPUT;
|
|
}
|
|
FREE(pwszBuffer);
|
|
|
|
// XXX If the command failed, we probably want to set the
|
|
// XXX current context to some NULL context so all commands fail
|
|
}
|
|
|
|
return dwErr;
|
|
}
|
|
|
|
DWORD
|
|
HandleShellPopd(
|
|
LPCWSTR pwszMachine,
|
|
LPWSTR *ppwcArguments,
|
|
DWORD dwCurrentIndex,
|
|
DWORD dwArgCount,
|
|
DWORD dwFlags,
|
|
LPCVOID pvData,
|
|
BOOL *pbDone
|
|
)
|
|
{
|
|
PLIST_ENTRY ple;
|
|
PCONTEXT_BUFFER pcb;
|
|
|
|
InitContextStack();
|
|
|
|
if (IsListEmpty(&leContextStackHead))
|
|
return NO_ERROR;
|
|
|
|
// Pop buffer off stack
|
|
ple = leContextStackHead.Flink;
|
|
pcb = CONTAINING_RECORD(ple, CONTEXT_BUFFER, le);
|
|
RemoveEntryList(ple);
|
|
|
|
// Copy buffer to current context
|
|
wcscpy( g_pwszContext, pcb->wszBuffer );
|
|
|
|
// Free buffer
|
|
FREE(pcb);
|
|
|
|
return NO_ERROR;
|
|
}
|