MISC.C

// THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF 
// ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
// THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
// PARTICULAR PURPOSE.
//
// Copyright 1993 - 1998 Microsoft Corporation. All Rights Reserved.
//
// MODULE: misc.c
//
// PURPOSE: Contains all helper functions "global" to the application.
//
// FUNCTIONS:
// CenterWindow - Center one window over another.
// ReceiveInBox - Reads incoming socket data.
// SendOutBox - Writes outgoing socket data.
// AtoH - Converts ascii string to network order hex
// BtoH - Converts ascii byte to hex
// CleanUp - closes sockets and detaches winsock dll
// GetAddrString - Puts IPX address into <network>.<node>.<socket> string format
// HtoA - Converts network order hex to ascii string
// HtoB - Converts hex byte to asci string
//
// COMMENTS:
//
//

#include <windows.h> // required for all Windows applications
#include <windowsx.h>
#include <wsipx.h>
#include "globals.h" // prototypes specific to this application



//
// FUNCTION: CenterWindow(HWND, HWND)
//
// PURPOSE: Center one window over another.
//
// PARAMETERS:
// hwndChild - The handle of the window to be centered.
// hwndParent- The handle of the window to center on.
//
// RETURN VALUE:
//
// TRUE - Success
// FALSE - Failure
//
// COMMENTS:
//
// Dialog boxes take on the screen position that they were designed
// at, which is not always appropriate. Centering the dialog over a
// particular window usually results in a better position.
//

BOOL CenterWindow(HWND hwndChild, HWND hwndParent)
{
RECT rcChild, rcParent;
int cxChild, cyChild, cxParent, cyParent;
int cxScreen, cyScreen, xNew, yNew;
HDC hdc;

// Get the Height and Width of the child window
GetWindowRect(hwndChild, &rcChild);
cxChild = rcChild.right - rcChild.left;
cyChild = rcChild.bottom - rcChild.top;

// Get the Height and Width of the parent window
GetWindowRect(hwndParent, &rcParent);
cxParent = rcParent.right - rcParent.left;
cyParent = rcParent.bottom - rcParent.top;

// Get the display limits
hdc = GetDC(hwndChild);
cxScreen = GetDeviceCaps(hdc, HORZRES);
cyScreen = GetDeviceCaps(hdc, VERTRES);
ReleaseDC(hwndChild, hdc);

// Calculate new X position, then adjust for screen
xNew = rcParent.left + ((cxParent - cxChild) / 2);
if (xNew < 0)
{
xNew = 0;
}
else if ((xNew + cxChild) > cxScreen)
{
xNew = cxScreen - cxChild;
}

// Calculate new Y position, then adjust for screen
yNew = rcParent.top + ((cyParent - cyChild) / 2);
if (yNew < 0)
{
yNew = 0;
}
else if ((yNew + cyChild) > cyScreen)
{
yNew = cyScreen - cyChild;
}

// Set it, and return
return SetWindowPos(hwndChild,
NULL,
xNew, yNew,
0, 0,
SWP_NOSIZE | SWP_NOZORDER);
}

//
// FUNCTION: ReceiveInBox(HWND, WPARAM, LPARAM, char *, int)
//
// PURPOSE: Reads incoming data from socket
//
// PARAMETERS:
// hWnd - Handle to current window
// uParam - WPARAM (unused)
// lParam - LPARAM contains event (FD_READ or FD_CLOSE).
// szRBuf - Receive Buffer
// cRBufLen - size of Receive Buffer
//
// RETURN VALUE:
//
// TRUE - Data Read
// FALSE - If FD_CLOSE message
//
// COMMENTS:
//
// Called if socket has data OR if it is closed. If closed post
// WM_DISCONNECTED message. Else read data and make sure it is
// NULL terminated.
//

BOOL ReceiveInBox(HWND hWnd, WPARAM uParam, LPARAM lParam, char * szRBuf, int cRBufLen)
{
char * pRBuf; // temp buf pointer
int cBytesRead; // count of bytes actually read


if (LOWORD(lParam) == FD_CLOSE) // Is this a FD_CLOSE event?
{
SendMessage(hWnd, MW_DISCONNECTED, 0, 0); // Yes, post message
return(FALSE);
}

pRBuf = szRBuf; // Set temp pointer
cRBufLen--; // Save room for null terminator

// read socket
if((cBytesRead = recv(sock, pRBuf, cRBufLen, 0)) != SOCKET_ERROR)
pRBuf += cBytesRead; // Move temp pointer to end of buffer

*pRBuf = 0; // Null terminate - if recv() failed, then prBuf will
// point to first byte of the buffer

return (TRUE); // We've got a buffer to display
}

//
// FUNCTION: SendOutBox(char *, int)
//
// PURPOSE: Reads incoming data from socket
//
// PARAMETERS:
// szSBuf - Send Buffer
// cSBufLen - size of Send Buffer
//
// COMMENTS:
//
// Writes send buffer to socket -- repeats until all data is sent.
//

void SendOutBox(char * szSBuf, int cSBufLen)
{
char * pSBuf;
int cBytesSent;

pSBuf = szSBuf; // Set temp pointer

while((cBytesSent = send(sock,
pSBuf,
cSBufLen,
0)) != SOCKET_ERROR)
{
pSBuf += cBytesSent;
cSBufLen -= cBytesSent;
if(!cSBufLen) return;
}
}

//
// FUNCTION: AtoH(char *, char *, int)
//
// PURPOSE: Converts ascii string to network order hex
//
// PARAMETERS:
// src - pointer to input ascii string
// dest - pointer to output hex
// destlen - size of dest
//
// COMMENTS:
//
// 2 ascii bytes make a hex byte so must put 1st ascii byte of pair
// into upper nibble and 2nd ascii byte of pair into lower nibble.
//

void AtoH(char * src, char * dest, int destlen)
{
char * srcptr;

srcptr = src;

while(destlen--)
{
*dest = BtoH(*srcptr++) << 4; // Put 1st ascii byte in upper nibble.
*dest++ += BtoH(*srcptr++); // Add 2nd ascii byte to above.
}
}

//
// FUNCTION: BtoH(char *, char *, int)
//
// PURPOSE: Converts ascii byte to numeric
//
// PARAMETERS:
// ch - ascii byte to convert
//
// RETURNS:
// associated numeric value
//
// COMMENTS:
//
// Will convert any hex ascii digit to its numeric counterpart.
// Puts in 0xff if not a valid hex digit.
//

unsigned char BtoH(char ch)
{
if (ch >= '0' && ch <= '9') return (ch - '0'); // Handle numerals
if (ch >= 'A' && ch <= 'F') return (ch - 'A' + 0xA); // Handle capitol hex digits
if (ch >= 'a' && ch <= 'f') return (ch - 'a' + 0xA); // Handle small hex digits
return(255);
}

//
// FUNCTION: CleanUp(void)
//
// PURPOSE: Protocol specific cleanup function
//
// COMMENTS:
//
// Deletes our two possible sockets (they might not exist which
// just means closesocket might return an error -- we don't care).
//

void CleanUp(void)
{
closesocket(SrvSock); // Close our server side socket
closesocket(sock); // Close our connection specific socket
WSACleanup(); // Nix the DLL
}

//
// FUNCTION: GetAddrString(PSOCKADDR_IPX, char *)
//
// PURPOSE: Converts IPX address to ascii string for displaying
//
// PARAMETERS:
// pSAddr - pointer to socket address struc
// dest - pointer to destination string
//
// COMMENTS:
//
// Address is in network order to use HtoA to convert to ascii.
//
// Final format is
// <8 char network address>.<12 char node address>.<4 char sock address>
//

void GetAddrString(PSOCKADDR_IPX pSAddr, char * dest)
{
char abuf[15]; // temp buffer
char * currptr; // temp destination pointer
int saddrlen = sizeof(struct sockaddr_ipx); // sizeof address struc

currptr = dest; // initialize destination pointer

HtoA((char *)&pSAddr->sa_netnum, abuf, 4); // convert network number
lstrcpy(currptr, abuf);
currptr += 8;
lstrcat(currptr, "."); // don't forget seperator
currptr++;

HtoA((char *)&pSAddr->sa_nodenum, abuf, 6); // convert node number
lstrcat(currptr, abuf);
currptr += 12;
lstrcat(currptr, "."); // seperator
currptr++;

HtoA((char *)&pSAddr->sa_socket, abuf, 2); // convert socket number
lstrcat(currptr, abuf);

}

//
// FUNCTION: HtoA(char *, char *, int)
//
// PURPOSE: Converts network ordered hex to ascii string
//
// PARAMETERS:
// src - pointer to network ordered hex
// dest - pointer to ascii string
// srclen - size of hex number in bytes
//
// COMMENTS:
//
// 1 byte hex = 2 bytes ascii so convert high order nibble with HtoB()
// then convert low order nibble. dest buffer better be 2*srclen + 1.
//

void HtoA(char * src, char * dest, int srclen)
{
char * destptr; // temp pointers
UCHAR * srcptr;

srcptr = (UCHAR *)src;
destptr = dest;

while(srclen--)
{
*destptr++ = HtoB((UCHAR)(*srcptr >> 4)); // Convert high order nibble
*destptr++ = HtoB((UCHAR)(*srcptr++ & 0x0F)); // Convert low order nibble
}
*destptr = 0; // Null terminator
}

//
// FUNCTION: HtoB(UCHAR)
//
// PURPOSE: Converts hex byte to ascii byte
//
// PARAMETERS:
// ch - Hex byte
//
// RETURNS:
// ascii byte
//
// COMMENTS:
//
// We actually only convert a nibble since 1 byte hex = 2 bytes ascii.
// So if ch > 0xf we just return 'X'.
//

char HtoB(UCHAR ch)
{
if (ch <= 9) return ('0' + ch); // handle decimal values
if (ch <= 0xf) return ('A' + ch - 10); // handle hexidecimal specific values
return('X'); // Someone screwed up
}


//---------------------------------------------------------------------------
//
// FUNCTION: GetStringRes (int id INPUT ONLY)
//
// COMMENTS: Load the resource string with the ID given, and return a
// pointer to it. Notice that the buffer is common memory so
// the string must be used before this call is made a second time.
//
//---------------------------------------------------------------------------

LPTSTR GetStringRes (int id)
{
static TCHAR buffer[MAX_PATH];

buffer[0]=0;
LoadString (GetModuleHandle (NULL), id, buffer, MAX_PATH);
return buffer;
}