/********************************************************************/
/**               Copyright(c) Microsoft Corp., 1990-1993          **/
/********************************************************************/
/* :ts=4 	This file uses 4 space hard tabs */

// ***	vrddbg.c - VRedir debug routines
//

#ifdef DEBUG

#include "precomp.h"
#pragma hdrstop

#pragma code_seg("PAGE")

#include <ifsdebug.h>

#pragma intrinsic (memcmp, memcpy, memset, strcat, strcmp, strcpy, strlen)

#define  MAXPRO            (2+2)
extern NETPRO rgNetPro[MAXPRO];
extern int cMacPro;
extern LPSTR    lpLogBuff;
extern int indxCur;
VOID
DispThisIOReq(
	pioreq pir
	);

VOID
DispThisResource(
	PRESOURCE pResource	
	);

VOID
DispThisFdb(
	PFDB pFdb
	);

VOID
DispThisFileInfo(
	PFILEINFO pFileInfo
	);

VOID
DispThisFindInfo(
	PFINDINFO pFindInfo
	);

extern pimh
DebugMenu(
	IFSMenu *pIFSMenu
	);

IFSMenuHand DispNetPro, DispResource, DispFdb, DispFileInfo, DispFindInfo, DispIOReq, DispLog;

IFSMenu	SHDMainMenu[] = {
	{"NetPro info"	, DispNetPro},
	{"Resource info", DispResource},
	{"Fdb info"		, DispFdb},
	{"OpenFile Info", DispFileInfo},
	{"Find Info"	, DispFindInfo},
	{"DisplayIOReq"	, DispIOReq},
    {"DisplayLog"   , DispLog},
	{0				, 0}
};

typedef struct {
    char  *pName;      // Command name (unique part uppercase, optional lowercase)
    int   (*pHandler)(char *pArgs);
} QD, *pQD;


int NetProCmd(char *pCmd);
int ResCmd(char *pCmd);
int FdbCmd(char *pCmd);
int FileInfoCmd(char *pCmd);
int FindInfoCmd(char *pCmd);
int IoReqCmd(char *pCmd);
int FindInfoCmd(char *pCmd);
int LogCmd(char *pCmd);

QD QueryDispatch[] = {
    { "NETPRO"    	, NetProCmd     },
    { "RES"         , ResCmd     	},
    { "FDB"     	, FdbCmd        },
    { "FILEINFO"    , FileInfoCmd   },
    { "FINDINFO"   	, FindInfoCmd   },
    { "IOREQ"   	, IoReqCmd      },
    { "LOG"         , LogCmd        },
	{ ""        	, 0             },
};


#define MAX_ARG_LEN 30
#define MAX_DEBUG_QUERY_COMMAND_LENGTH 100

unsigned char DebugQueryCmdStr[MAX_DEBUG_QUERY_COMMAND_LENGTH+1] = "";
ULONG DebugQueryCmdStrLen = MAX_DEBUG_QUERY_COMMAND_LENGTH;
unsigned char CmdArg[MAX_ARG_LEN+1] = {0};
unsigned char vrgchBuffDebug[MAX_PATH+1];

/*
    GetArg - Gets a command line argument from a string.

    IN          ppArg = pointer to pointer to argument string
    OUT        *ppArg = pointer to next argument, or NULL if this was the last.
    Returns     Pointer to uppercase ASCIZ argument with delimeters stripped, or NULL if
                no more arguments.

    Note        Not reentrant

*/

unsigned char *GetArg(unsigned char **ppArg)
{
    // Note - Always returns at least one blank argument if string is valid, even
    //        if the string is empty.

    unsigned char *pDest = CmdArg;
    unsigned char c;
    ULONG i;

    #define pArg (*ppArg)

    // If end of command already reached, fail

    if (!pArg)
        return NULL;

    // Skip leading whitespace

    while (*pArg == ' ' || *pArg == '\t')
        pArg++;

    // Copy the argument

    for (i = 0; i < MAX_ARG_LEN; i++) {
        if ((c = *pArg) == 0 || c == '\t' || c == ' ' || c == ';' ||
                          c == '\n' || c == ',')
            break;
        if (c >= 'a' && c <= 'z')
            c -= ('a' - 'A');
        *(pDest++) = c;
        pArg++;
    }

    // Null terminate the result

    *pDest = '\0';

    // Skip trailing whitespace

    while (*pArg == ' ' || *pArg == '\t')
        pArg++;

    // strip up to one comma

    if (*pArg == ',')
        pArg++;

    // If end of command reached, make next request fail

    else if (*pArg == 0 || *pArg == ';' || *pArg == '\n')
        pArg = NULL;

    // return copy

    return CmdArg;

    #undef pArg
}

/*
    AtoI - Convert a string to a signed or unsigned integer

    IN          pStr = ASCIZ representation of number with optional leading/trailing
                       whitespace and optional leading '-'.
                Radix = Radix to use for conversion (2, 8, 10, or 16)
    OUT        *pResult = Numeric result, or unchanged on failure
    Returns     1 on success, 0 if malformed string.

    Note        Not reentrant

*/
ULONG AtoI(unsigned char *pStr, ULONG Radix, ULONG *pResult)
{
    ULONG r = 0;
    ULONG Sign = 0;
    unsigned char c;
    ULONG d;

    while (*pStr == ' ' || *pStr == '\t')
        pStr++;

    if (*pStr == '-') {
        Sign = 1;
        pStr++;
    }

    if (*pStr == 0)
        return 0;                   // Empty string!

    while ((c = *pStr) != 0 && c != ' ' && c != '\t') {
        if (c >= '0' && c <= '9')
            d = c - '0';
        else if (c >= 'A' && c <= 'F')
            d = c - ('A' - 10);
        else if (c >= 'a' && c <= 'f')
            d = c - ('a' - 10);
        else
            return 0;               // Not a digit
        if (d >= Radix)
            return 0;               // Not in radix
        r = r*Radix+d;
        pStr++;
    }

    while (*pStr == ' ' || *pStr == '\t')
        pStr++;

    if (*pStr != 0)
        return 0;                   // Garbage at end of string

    if (Sign)
        r = (ULONG)(-(int)r);
    *pResult = r;

    return 1;                       // Success!

}

VOID
*GetPtr(char *pCmd)
{
	char *pch;
	int p;
	
	pch = GetArg(&pCmd);
	
	//dprintf("cmd = '%s'\n");
	if (*pch == 0 || !AtoI(pch, 16, &p))
 		return 0;

	return (VOID *) p;
}

int
CmdDispatch(char *pCmdName, char *pCmd)
{
	int ret = 0;
	int i=0;
	pQD	pq;

	pq = QueryDispatch;

	while (pq->pName[0]) {
		if (strcmp(pCmdName, pq->pName) == 0) {
		    ret = (*pq->pHandler)(pCmd);
			DbgPrint("\n");
			break;
		}
		pq++;
	}

	return ret;
}

//** Debug Command Handlers

int
NetProCmd(char *pCmd)
{
	
	DispNetPro("");

	return 1;
}

int
IoReqCmd(char *pCmd)
{
	pioreq pir;

	if (pir = GetPtr(pCmd))
		DispThisIOReq(pir);
	else
		return 0;

	return 1;
}


int
ResCmd(char *pCmd)
{
	DispResource(pCmd);
	return 1;
}

int
FdbCmd(char *pCmd)
{
	PFDB pFdb;


	if (pFdb = GetPtr(pCmd)){
		DispThisFdb(pFdb);
	}

	return 1;
}

int
FileInfoCmd(char *pCmd)
{
	PFILEINFO pF;

	if (pF = GetPtr(pCmd))
		DispThisFileInfo(pF);

	return 1;
}

int
FindInfoCmd(char *pCmd)
{

	return 1;
}

int
LogCmd(char *pCmd)
{
    DispLog(pCmd);
}

// **	SHDDebug - handle Debug_Query request from windows
//

VOID
SHDDebug(unsigned char *pCmd)
{
	pimh phand;
	char *pCmdName;

//	dprintf("pCmd = '%s'\n", pCmd);
	//see if we got an explicit command
	pCmdName = GetArg(&pCmd);	

//	dprintf("pCmdName = (%x) '%s'\n", pCmdName, pCmdName);	
	if (*pCmdName != 0) { //got a command, try to process it
		if (!CmdDispatch(pCmdName, pCmd))  {
			DbgPrint("%* Shadow Command Options:\n");
			DbgPrint("%* NETPRO             ----- dump network provider info\n");
			DbgPrint("%* RES [addr]         ---- dump resource info\n");
			DbgPrint("%* FDB [addr]         ---- dump File Descriptor Block\n");
			DbgPrint("%* FILEINFO [addr]    --- dump per open file structure\n");
			DbgPrint("%* FINDINFO [addr]    --- dump findinfo structure\n");
			DbgPrint("%* IOREQ [addr]       --- dump IOReq structure\n");
    		DbgPrint("%* LOG                --- show trace log\n");
    	}
	} else {
		//no args passed, do the menu thing
		while ((phand=DebugMenu(SHDMainMenu)) != 0) {
			if (phand(0) != 0)
				return;
		}
	}
	return;
}


/*+++

Actual display functions

+++*/


VOID
DispThisIOReq(
	pioreq pir
	)
{
    // Display the ioreq structure
	DbgPrint("%*IoReq = \t\t%8.8x \n", pir );
	DbgPrint("%*ir_length=\t\t%x\n", pir->ir_length);
    DbgPrint("%*ir_flags=\t\t%x\n", pir->ir_flags);
    DbgPrint("%*ir_user=\t\t%x\n", pir->ir_user);
	DbgPrint("%*ir_sfn=\t\t%x\n", pir->ir_sfn);
    DbgPrint("%*ir_pid=\t\t%x\n", pir->ir_pid);
    DbgPrint("%*ir_ppath=\t\t%x\n", pir->ir_ppath);
	DbgPrint("%*ir_aux1=\t\t%x\n", pir->ir_aux1);
    DbgPrint("%*ir_data=\t\t%x\n", pir->ir_data);
    DbgPrint("%*ir_options=\t\t%x\n", pir->ir_options);
	DbgPrint("%*ir_error=\t\t%x\n", pir->ir_error);
	DbgPrint("%*ir_rh=\t\t%x\n", pir->ir_rh);
	DbgPrint("%*ir_fh=\t\t%x\n", pir->ir_fh);
	DbgPrint("%*ir_pos=\t\t%x\n", pir->ir_pos);
    DbgPrint("%*ir_aux2=\t\t%x\n", pir->ir_aux2);
    DbgPrint("%*ir_pev=\t\t%x\n", pir->ir_pev);
}

int DispIOReq(
	char *pCmd
	)
{
	pioreq pir;

	if (pir = GetPtr(pCmd))
	{
		DispThisIOReq(pir);
		return (1);
	}
	return (0);
}
int
DispNetPro(
	char *pcl
	)
{
	int i;

	if (cMacPro > 1){
		DbgPrint("%d redirs hooked \n", cMacPro-1);

		for (i=1; i< cMacPro; ++i){
			DbgPrint("Info for Redir # %d \n", i);

			DbgPrint("Head of Resource Chain = \t%x\n", rgNetPro[i].pheadResource);
			DbgPrint("Shadow Connect Function = \t%x\n", rgNetPro[i].pOurConnectNet);
			DbgPrint("Redir Connect Function = \t%x\n", rgNetPro[i].pConnectNet);
		}
		return (1);
	}
	else {
		DbgPrint("No Redirs have been hooked \n");
		return (0);
	}
}


int
DispResource(
	char *pCmd
	)
{
	PRESOURCE pResource = GetPtr(pCmd);

	if (pResource)
	{
		DispThisResource(pResource);

	}
	else
	{
		if (cMacPro > 1)
		{
			pResource = rgNetPro[1].pheadResource;
			while (pResource)
			{
				DispThisResource(pResource);
				pResource = pResource->pnextResource;
			}
		}
	}
}

int
DispFdb(
	char *pCmd
	)
{
	PFDB pFdb = GetPtr(pCmd);

	if (pFdb)
	{
		DispThisFdb(pFdb);
		return (1);
	}
	return (0);
}

int
DispFileInfo(
	char *pCmd
	)
{
	PFILEINFO pFileInfo = GetPtr(pCmd);

	if (pFileInfo)
	{
		DispThisFileInfo(pFileInfo);
		return (1);
	}
	return (0);
}

int
DispFindInfo(
	char *pCmd
	)
{
	PFINDINFO pFindInfo = GetPtr(pCmd);

	if (pFindInfo)
	{
		DispThisFindInfo(pFindInfo);
		return (1);
	}
	return (0);
}

int
DispLog(
	char *pCmd
    )
{
    int indxT=0, len;
    LPSTR   lpszT;

    pCmd;

    lpszT = lpLogBuff;

    while (indxCur > indxT)
    {
        DbgPrint(("%s"), lpszT);

        for (len=1; (*(lpszT+len) != 0xa) && ((indxT+len) < indxCur); ++len);

        // step over the string
        lpszT += len;
        indxT += len;
    }

}

/*+++

Helper Functions

+++*/


VOID
DispThisResource(
	PRESOURCE pResource
	)
{
	DbgPrint("Resource \t%x \n", pResource);
	PpeToSvr(pResource->pp_elements, vrgchBuffDebug, MAX_PATH, BCS_OEM);
	DbgPrint("Share name: \t%s \n", vrgchBuffDebug);
	DbgPrint("Next Resource \t%x \n", pResource->pnextResource);
	DbgPrint("FileInfo structures list \t%x \n", pResource->pheadFileInfo);
	DbgPrint("FindInfo structures list \t%x \n", pResource->pheadFindInfo);
	DbgPrint("FDB structures list \t%x \n", pResource->pheadFdb);
	DbgPrint("hServer: \t%x\n", pResource->hServer);
	DbgPrint("Root shadow: \t%x\n", pResource->hRoot);
	DbgPrint("usFlags \t%x\n", (ULONG)(pResource->usFlags));
	DbgPrint("usLocalFlags \t%x\n", (ULONG)(pResource->usLocalFlags));
	DbgPrint("Our Network Provider \t%x\n", pResource->pOurNetPro);
	DbgPrint("Providers resource handle \t%x\n", pResource->rhPro);
	DbgPrint("fh_t \t%x\n", pResource->fhSys);
	DbgPrint("Providers Volume Function table \t%x\n", pResource->pVolTab);
	DbgPrint(" Count of locks on this resource \t%x\n", pResource->cntLocks);
	DbgPrint(" Bitmap of mapped drives \t%x\n", pResource->uDriveMap);

}

VOID
DispThisFdb(
	PFDB pFdb
	)
{

	DbgPrint("\n");
	memset(vrgchBuffDebug, 0, sizeof(vrgchBuffDebug));
	UniToBCSPath(vrgchBuffDebug, &(pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
	DbgPrint("****** Fdb for \t%s ", vrgchBuffDebug);
	memset(vrgchBuffDebug, 0, sizeof(vrgchBuffDebug));
	PpeToSvr(pFdb->pResource->pp_elements, vrgchBuffDebug, MAX_PATH, BCS_OEM);
	DbgPrint("on \t%s \n", vrgchBuffDebug);

	DbgPrint("Next Fdb: \t%x \n", pFdb->pnextFdb);
	DbgPrint("Resource: \t%x\n", pFdb->pResource);
	DbgPrint("usFlags: \t%x\n", (ULONG)(pFdb->usFlags));
	DbgPrint("Total # of opens: \t%x\n", (ULONG)(pFdb->usCount));
	DbgPrint("File Inode: \t%x\n", pFdb->hShadow);
	DbgPrint("Dir Inode: \t%x\n", pFdb->hDir);

}


VOID
DispThisFileInfo(
	PFILEINFO pFileInfo
	)
{

	DbgPrint("\n");
	memset(vrgchBuffDebug, 0, sizeof(vrgchBuffDebug));
	UniToBCSPath(vrgchBuffDebug, &(pFileInfo->pFdb->sppathRemoteFile.pp_elements[0]), MAX_PATH, BCS_OEM);
	DbgPrint("****** FileInfo for \t%s ", vrgchBuffDebug);
	memset(vrgchBuffDebug, 0, sizeof(vrgchBuffDebug));
	PpeToSvr(pFileInfo->pResource->pp_elements, vrgchBuffDebug, MAX_PATH, BCS_OEM);
	DbgPrint("on \t%s \n", vrgchBuffDebug);

	DbgPrint(" Next FileInfo \t%x\n", pFileInfo->pnextFileInfo);
	DbgPrint(" Resource off which it is hangin%x\n", pFileInfo->pResource);
	DbgPrint(" Shadow file handle \t%x\n", pFileInfo->hfShadow);
	DbgPrint(" pFdb: %x\n", pFileInfo->pFdb);
	DbgPrint(" providers file handle: \t%x\n", pFileInfo->fhProFile);
	DbgPrint(" providers file function table \t%x\n", pFileInfo->hfFileHandle);
	DbgPrint(" Acess-share flags for this open \t%x\n", (ULONG)(pFileInfo->uchAccess));
	DbgPrint(" usFlags: \t%x\n", (ULONG)(pFileInfo->usFlags));
	DbgPrint(" usLocalFlags: \t%x\n", (ULONG)(pFileInfo->usLocalFlags));
	DbgPrint(" sfnFile: \t%x\n", pFileInfo->sfnFile);
	DbgPrint(" pidFile: \t%x\n", pFileInfo->pidFile);
	DbgPrint(" userFile: \t%x\n", pFileInfo->userFile);

}

VOID
DispThisFindInfo(
	PFINDINFO pFindInfo
	)
{
}


#endif
