MISC.C
资源名称:MSDN_VC98.zip [点击查看]
上传用户:bangxh
上传日期:2007-01-31
资源大小:42235k
文件大小:18k
源码类别:
Windows编程
开发平台:
Visual 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 (C) 1993-1997 Microsoft Corporation. All Rights Reserved.
- //
- // MODULE: misc.c
- //
- // PURPOSE: Contains all helper functions "global" to the application.
- //
- // FUNCTIONS:
- // CenterWindow - Center one window over another.
- // AtoH - Converts ascii to network order hex
- // BtoH - Converts ascii byte to numeric
- // deregistername - Notifies "Available" peers of clients non-availability
- // senddatamessage - Sends a message to a client node
- // recvdatamessage - reads an entire message
- // UpdateClientList - Updates Client Status Listbox
- // MakeServSock - Attempts to initialize socket for listening
- //
- // COMMENTS:
- //
- //
- #include <windows.h> // required for all Windows applications
- #include <windowsx.h>
- #include <nspapi.h>
- #include <svcguid.h>
- #include <wsipx.h>
- #include <wsnetbs.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: 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: deregistername(char *)
- //
- // PURPOSE: Removes client's availability from other "AVAILABLE" clients
- //
- // PARAMETERS:
- // name - name to deregister
- //
- // RETURNS:
- // nothing
- //
- // COMMENTS:
- //
- // Between the time when a client connects to the server and when it starts
- // a chat, the client is in "AVAILABLE" state. It keeps of list of other
- // available peers. deregistername removes a previously available client
- // from the lists of all the other available clients
- //
- void deregistername(char * name)
- {
- int j;
- // Set up message header
- xferbuf.hdr.signature = MYSIGNATURE;
- xferbuf.hdr.length = REALLEN(name) + HDRSIZE;
- xferbuf.hdr.command = DEREGISTER_NAME;
- // Message data is simply the name
- lstrcpy(xferbuf.data, name);
- // Send to every connected client whose status is SOCKET_AVAILABLE
- for (j = 0; j < NextFree; j++)
- {
- if (ConnectedSockets[j].status == SOCKSTAT_AVAILABLE)
- {
- senddatamessage(ConnectedSockets[j].sock, &xferbuf);
- }
- }
- return;
- }
- //
- // FUNCTION: senddatamessage(SOCKET, LPDATAMSG)
- //
- // PURPOSE: Sends a message to a client
- //
- // PARAMETERS:
- // sock - Client socket to send data on
- // sendbuf - message to send
- //
- // RETURNS:
- // TRUE - message sent
- //
- // COMMENTS:
- //
- // Performs send() until entire message is sent
- //
- BOOL senddatamessage (SOCKET sock, LPDATAMSG sendbuf)
- {
- int totalbytes, bytessent;
- int thissendsize;
- bytessent = 0; // start count of bytessent
- totalbytes = sendbuf->hdr.length; // read total bytes from message header
- while(bytessent < totalbytes)
- {
- // We may not be able to send the entire message with a single
- // send. Therefore continue sending until the whole thing
- // is gone.
- if ((thissendsize = send(sock,
- (char *)sendbuf + bytessent,
- totalbytes - bytessent,
- 0)) == SOCKET_ERROR)
- {
- // Error
- return FALSE;
- }
- bytessent += thissendsize;
- }
- return TRUE;
- }
- //
- // FUNCTION: recvdatamessage(LPSOCKDATA, LPDATAMSG)
- //
- // PURPOSE: Receives a message from a client
- //
- // PARAMETERS:
- // lpSockdat - pointer to sockdata struct of socket we are receiving data on.
- // recvbuf - buffer to receive data into.
- //
- // RETURNS:
- // TRUE - message received
- // FALSE - message not received
- //
- // COMMENTS:
- // Performs recv() until entire message is received
- //
- BOOL recvdatamessage (LPSOCKDATA lpSockdat, LPDATAMSG recvbuf)
- {
- int readsize, totalbytesread, msgsize, bytesread;
- if (lpSockdat->type == SOCK_SEQPACKET)
- {
- // Message mode protocol!! Just post one big read.
- readsize = sizeof(*recvbuf);
- }
- else
- {
- // Stream mode protocol!! Just read header...then read data (data size determined
- // from header)
- readsize = HDRSIZE;
- }
- if((totalbytesread = recv(lpSockdat->sock, (char *)recvbuf, readsize, 0)) == SOCKET_ERROR)
- {
- // ERROR -- just return dropping message
- return FALSE;
- }
- // Check for my signature at the beginning of the message
- if(recvbuf->hdr.signature != MYSIGNATURE)
- {
- // I've received some data that's in mid message--drop it
- return FALSE;
- }
- // Read size of message
- msgsize = recvbuf->hdr.length;
- readsize = msgsize - totalbytesread;
- while(totalbytesread < msgsize)
- {
- // we should only get hear for stream sockets
- if((bytesread = recv(lpSockdat->sock,
- (char *)recvbuf + totalbytesread,
- readsize,
- 0)) == SOCKET_ERROR)
- {
- if (WSAGetLastError() != WSAEWOULDBLOCK)
- {
- // ERROR -- throw out message
- return FALSE;
- }
- // If you got a WSAWOULDBLOCK error, just keep trying...it shouldn't take
- // too much longer for the rest of the message to get here. Let's hope
- // we don't hog the CPU so the data doesn't get to us.
- }
- totalbytesread += bytesread;
- readsize -= bytesread;
- }
- return TRUE;
- }
- //
- // FUNCTION: UpdateClientList(char *, int, char *)
- //
- // PURPOSE: Updates Client Status List box
- //
- // PARAMETERS:
- // name - name of client to update
- // status - status of client to display
- // peername - connected peer for status = IN_SESSION
- //
- // RETURNS:
- // nothing
- //
- // COMMENTS:
- // Finds and updates client status in listbox, or adds
- // it if client is new
- //
- void UpdateClientList(char * name, int status, char * peername)
- {
- int index;
- char outtext[80];
- // Find list box entry with name in it
- index = SendMessage(hwndClientList,
- LB_FINDSTRING,
- (WPARAM)-1,
- (LPARAM)name);
- // Delete the entry--we'll add a new entry below
- SendMessage(hwndClientList, LB_DELETESTRING, index, 0);
- switch (status)
- {
- case SOCKSTAT_CLOSED: // No new entry required. Just return.
- return;
- case SOCKSTAT_AVAILABLE: // build available entry
- wsprintf(outtext, GetStringRes(IDS_AVAILABLE), name);
- break;
- case SOCKSTAT_INSESSION: // build in_session entry
- wsprintf(outtext, GetStringRes (IDS_SESSION), name, peername);
- break;
- case SOCKSTAT_REQSESSION: // build reqsession entry
- wsprintf(outtext, GetStringRes(IDS_SESSION_SETUP), name, peername);
- }
- // Add the new list box entry to the client status list box
- SendMessage(hwndClientList, LB_ADDSTRING, 0, (LPARAM)&outtext);
- }
- //
- // FUNCTION: MakeServSock(HWND, LPSOCKDATA, LPPROTOCOL_INFO)
- //
- // PURPOSE: Attempts to initialize server side socket for listening
- //
- // PARAMETERS:
- // hwnd - handle to main window
- // ServSocks - SOCKDATA struct to hold socket specific information
- // lpProtBuf - PROTOCOL_INFO struct describing protocol to
- // attempt listen on
- //
- // RETURNS:
- // TRUE - Listen successfully posted
- // FALSE - Initialization failed
- //
- // COMMENTS:
- // Given the protocol triple in the PROTOCOL_INFO struct, we call
- // socket(), then GetAddressByName(), then bind(), listen(), and
- // finally WSAAsyncSelect() to get socket it appropriate state
- // for listening. If we fail at any point, then cleanup and do
- // not use protocol
- //
- BOOL MakeServSock(HWND hwnd, LPSOCKDATA ServSocks, LPPROTOCOL_INFO lpProtBuf)
- {
- CSADDR_INFO CSABuf[10];
- DWORD dwCSABufsize = sizeof(CSABuf);
- GUID guidNW = SVCID_NETWARE(NWCHATID); // Macro generates GUID using hard coded NetWare Service Type
- GUID guidDNS = SVCID_TCP(DNSCHATID); // Macro generates GUID using hard coded port
- LPSOCKADDR_NB lpNBaddr;
- // open socket using protocol defined by PROTOCOL_INFO structure
- if ((ServSocks->sock = socket(lpProtBuf->iAddressFamily,
- lpProtBuf->iSocketType,
- lpProtBuf->iProtocol)) == SOCKET_ERROR)
- {
- // ERROR
- return FALSE; // This will reuse the current ServSocks structure
- }
- // Populate SOCKDATA structure
- ServSocks->status = SOCKSTAT_INIT;
- ServSocks->type = lpProtBuf->iSocketType;
- ServSocks->protocol = lpProtBuf->iProtocol;
- ServSocks->currconnects = 0;
- ServSocks->lpProtocolName = lpProtBuf->lpProtocol;
- // ***********************************************************************
- //
- // Below we will be calling GetAddressByName with the RES_SERVICE
- // option in order to find the necessary sockaddr structure to use
- // for the following bind() call. At this point, GetAddressByName()
- // only supports the DNS and the SAP/Bindery name spaces. Ultimately
- // a single call to GetAddressByName will return information on
- // all available protocols, but this requires a central database
- // which is currently not available. In the mean time we will make
- // name space specific calls to GetAddressByName.
- //
- // ***********************************************************************
- switch (lpProtBuf->iAddressFamily)
- {
- case AF_IPX:
- // Use SAP/Bindery Name Space
- if (GetAddressByName(0, // Since GUID is name space specific, we don't need to specify distinct name space.
- &guidNW, // GUID defined by NetWare service type.
- "GLOBAL CHAT SERVER", // This parameter is actually not used for RES_SERVICE calls.
- NULL, // Since GUID implies the protocol, we don't need to specify a distinct one.
- RES_SERVICE, // Specifies that we are just looking for local address to bind to.
- NULL, // Currently not supported
- CSABuf, // Structure which will hold information for bind() call
- &dwCSABufsize, // Size of CSABuf
- NULL, // Currently not supported
- NULL) // Currently not supported
- < 1) // We need at least one address returned in order to bind()
- {
- // Error--cleanup
- closesocket(ServSocks->sock);
- return FALSE;
- }
- // Copy sockaddr info and addresslength
- memcpy(&ServSocks->addr, CSABuf[0].LocalAddr.lpSockaddr, sizeof(struct sockaddr));
- ServSocks->addrlen = CSABuf[0].LocalAddr.iSockaddrLength;
- break;
- case AF_INET:
- // Use DNS Name Space
- if (GetAddressByName(0, // Since GUID is name space specific, we don't need to specify
- &guidDNS, // GUID defined by TCP port number
- "globchat", // This parameter is actually not used for RES_SERVICE calls
- NULL, // GUID implies protocol so no need to specify
- RES_SERVICE, // Specifies that we are trying to find local address to bind to
- NULL, // Currently not supported
- CSABuf, // Results buffer
- &dwCSABufsize, // Size of results buffer
- NULL, // Not supported
- NULL) // Not supported
- < 1) // Need at least one address returned in order to bind()
- {
- // Error -- cleanup
- closesocket(ServSocks->sock);
- return FALSE;
- }
- // Copy sockaddr info and address length
- memcpy(&ServSocks->addr, CSABuf[0].LocalAddr.lpSockaddr, sizeof(struct sockaddr));
- ServSocks->addrlen = CSABuf[0].LocalAddr.iSockaddrLength;
- break;
- case AF_NETBIOS:
- // no netbios name space provider so we will simulate GetAddressByName() results
- lpNBaddr = (LPSOCKADDR_NB)&ServSocks->addr;
- SET_NETBIOS_SOCKADDR(lpNBaddr,
- NETBIOS_GROUP_NAME,
- "GLOBSERV",
- 0);
- ServSocks->addrlen = lpProtBuf->iMaxSockAddr;
- break;
- }
- // We have an address to bind() to, so do it!
- if (bind(ServSocks->sock,
- &ServSocks->addr,
- ServSocks->addrlen) == SOCKET_ERROR)
- {
- // Error -- cleanup
- closesocket(ServSocks->sock);
- return FALSE;
- }
- // Find out the specific local address
- if (getsockname(ServSocks->sock,
- &ServSocks->addr,
- &ServSocks->addrlen) == SOCKET_ERROR)
- {
- // Error -- better cleanup
- closesocket(ServSocks->sock);
- return FALSE;
- }
- // Listen on the socket
- if (listen(ServSocks->sock, 5) == SOCKET_ERROR)
- {
- // Error -- cleanup
- closesocket(ServSocks->sock);
- return FALSE;
- }
- // Set up window message to indicate connection
- if (WSAAsyncSelect(ServSocks->sock,
- hwnd,
- MW_CONNECTED,
- FD_ACCEPT) == SOCKET_ERROR)
- {
- // Error -- cleanup
- closesocket(ServSocks->sock);
- return FALSE;
- }
- // Success!!!
- return TRUE;
- }
- //---------------------------------------------------------------------------
- //
- // 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;
- }