473 lines
11 KiB
C
473 lines
11 KiB
C
|
/*++
|
|||
|
|
|||
|
Copyright (c) 1990-1992 Microsoft Corporation
|
|||
|
|
|||
|
Module Name:
|
|||
|
|
|||
|
MSG.C
|
|||
|
|
|||
|
Abstract:
|
|||
|
|
|||
|
Test Routines for the Service Controller.
|
|||
|
|
|||
|
Author:
|
|||
|
|
|||
|
Dan Lafferty (danl) 08-May-1991
|
|||
|
|
|||
|
Environment:
|
|||
|
|
|||
|
User Mode - Win32
|
|||
|
|
|||
|
Revision History:
|
|||
|
|
|||
|
08-May-1991 danl
|
|||
|
created
|
|||
|
|
|||
|
--*/
|
|||
|
//
|
|||
|
// INCLUDES
|
|||
|
//
|
|||
|
#include <nt.h> // DbgPrint prototype
|
|||
|
#include <ntrtl.h> // DbgPrint prototype
|
|||
|
#include <nturtl.h> // needed for winbase.h
|
|||
|
|
|||
|
#include <stdlib.h> // atoi
|
|||
|
#include <stdio.h> // printf
|
|||
|
#include <string.h> // strcmp
|
|||
|
#include <windows.h> // win32 typedefs
|
|||
|
#include <lmerr.h> // NERR_ error codes
|
|||
|
#include <windef.h> // win32 typedefs
|
|||
|
#include <lmcons.h>
|
|||
|
#include <lmmsg.h>
|
|||
|
#include <tstring.h> // Unicode
|
|||
|
|
|||
|
//
|
|||
|
// FUNCTION PROTOTYPES
|
|||
|
//
|
|||
|
VOID
|
|||
|
DisplayStatus (
|
|||
|
IN LPBYTE InfoStruct2,
|
|||
|
IN DWORD level
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
ConvertToUnicode(
|
|||
|
OUT LPWSTR *UnicodeOut,
|
|||
|
IN LPSTR AnsiIn
|
|||
|
);
|
|||
|
|
|||
|
BOOL
|
|||
|
MakeArgsUnicode (
|
|||
|
DWORD argc,
|
|||
|
PUCHAR argv[]
|
|||
|
);
|
|||
|
|
|||
|
|
|||
|
/****************************************************************************/
|
|||
|
VOID __cdecl
|
|||
|
main (
|
|||
|
int argc,
|
|||
|
PUCHAR argvA[]
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Allows manual testing of the Messenger Service by typing commands on
|
|||
|
the command line such as:
|
|||
|
|
|||
|
|
|||
|
msg add danl - adds a name (danl).
|
|||
|
msg del danl - deletes a name (danl).
|
|||
|
msg enum - enumerates the names (level 1)
|
|||
|
msg enum -l1 - enumerates the names (level 1)
|
|||
|
msg enum -l0 - enumerates the names (level 0)
|
|||
|
msg enum rh= 2 - enum with resume handle =2 (level1)
|
|||
|
msg enum maxlen= 50 - Does an enum with a 50 byte buffer.
|
|||
|
msg query danl - gets info on danl. (level 1)
|
|||
|
msg query danl -l0 - gets info on danl. (level 0)
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
|
|||
|
{
|
|||
|
NET_API_STATUS status;
|
|||
|
LPBYTE InfoStruct;
|
|||
|
DWORD entriesRead;
|
|||
|
DWORD totalEntries;
|
|||
|
DWORD resumeHandle;
|
|||
|
DWORD prefMaxLen;
|
|||
|
DWORD level;
|
|||
|
DWORD specialFlag = FALSE;
|
|||
|
DWORD i;
|
|||
|
WCHAR name[50];
|
|||
|
LPWSTR *argv;
|
|||
|
LPWSTR pServerName;
|
|||
|
LPTSTR *FixArgv;
|
|||
|
INT argIndex;
|
|||
|
|
|||
|
|
|||
|
if (argc <2) {
|
|||
|
printf("ERROR: no command was given! (add, del, enum, query)\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Make the arguments unicode if necessary.
|
|||
|
//
|
|||
|
argv = (LPWSTR *)argvA;
|
|||
|
|
|||
|
#ifdef UNICODE
|
|||
|
|
|||
|
if (!MakeArgsUnicode(argc, (PUCHAR *)argv)) {
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
#endif
|
|||
|
FixArgv = (LPTSTR *)argv;
|
|||
|
|
|||
|
pServerName = NULL;
|
|||
|
argIndex = 1;
|
|||
|
|
|||
|
if (STRNCMP (FixArgv[1], TEXT("\\\\"), 2) == 0) {
|
|||
|
pServerName = FixArgv[1];
|
|||
|
argIndex = 2;
|
|||
|
}
|
|||
|
|
|||
|
if (_wcsicmp (FixArgv[argIndex], L"enum" ) == 0 ) {
|
|||
|
|
|||
|
|
|||
|
resumeHandle = 0;
|
|||
|
level = 1;
|
|||
|
prefMaxLen = 0xffffffff;
|
|||
|
|
|||
|
if (argc > argIndex+1) {
|
|||
|
if (_wcsicmp (FixArgv[argIndex+1], L"rh=") == 0) {
|
|||
|
specialFlag = TRUE;
|
|||
|
if (argc > argIndex+2) {
|
|||
|
resumeHandle = wtol(FixArgv[argIndex+2]);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
if (_wcsicmp (FixArgv[argIndex+1], L"-l0") == 0) {
|
|||
|
specialFlag = TRUE;
|
|||
|
level = 0;
|
|||
|
}
|
|||
|
if (_wcsicmp (FixArgv[argIndex+1], L"-l2") == 0) {
|
|||
|
specialFlag = TRUE;
|
|||
|
level = 2;
|
|||
|
}
|
|||
|
if (_wcsicmp (FixArgv[argIndex+1], L"-l3") == 0) {
|
|||
|
specialFlag = TRUE;
|
|||
|
level = 3;
|
|||
|
}
|
|||
|
if (_wcsicmp (FixArgv[argIndex+1], L"maxlen=") == 0) {
|
|||
|
specialFlag = TRUE;
|
|||
|
if (argc > argIndex+2) {
|
|||
|
prefMaxLen = wtol(FixArgv[argIndex+2]);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
if ( (argc < argIndex+2) ||
|
|||
|
(specialFlag == TRUE) && (argc < argIndex+4) ) {
|
|||
|
|
|||
|
status = NetMessageNameEnum (
|
|||
|
pServerName, // ServerName - Local version
|
|||
|
level, // Level
|
|||
|
&InfoStruct, // return status buffer pointer
|
|||
|
prefMaxLen, // preferred max length
|
|||
|
&entriesRead, // entries read
|
|||
|
&totalEntries, // total entries
|
|||
|
&resumeHandle); // resume handle
|
|||
|
|
|||
|
if ( (status == NERR_Success) ||
|
|||
|
(status == ERROR_MORE_DATA) ){
|
|||
|
|
|||
|
printf("Enum: entriesRead = %d\n", entriesRead);
|
|||
|
printf("Enum: totalEntries = %d\n", totalEntries);
|
|||
|
printf("Enum: resumeHandle = %d\n", resumeHandle);
|
|||
|
|
|||
|
for (i=0; i<entriesRead; i++) {
|
|||
|
DisplayStatus(InfoStruct,level);
|
|||
|
switch(level) {
|
|||
|
case 0:
|
|||
|
InfoStruct += sizeof(MSG_INFO_0);
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
InfoStruct += sizeof(MSG_INFO_1);
|
|||
|
break;
|
|||
|
default:
|
|||
|
printf("Bad InfoLevel\n");
|
|||
|
}
|
|||
|
|
|||
|
}
|
|||
|
}
|
|||
|
else {
|
|||
|
printf("[msg] NetServiceEnum FAILED, rc = %ld\n", status);
|
|||
|
if (InfoStruct != NULL) {
|
|||
|
DisplayStatus(InfoStruct,level);
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else if (_wcsicmp (FixArgv[argIndex], L"query") == 0) {
|
|||
|
|
|||
|
level = 1;
|
|||
|
|
|||
|
if (argc > argIndex+1 ) {
|
|||
|
wcscpy(name, FixArgv[argIndex+1]);
|
|||
|
}
|
|||
|
if (argc > argIndex+2) {
|
|||
|
if (_wcsicmp (FixArgv[argIndex+2], TEXT("-l0")) ==0) {
|
|||
|
level = 0;
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
status = NetMessageNameGetInfo (
|
|||
|
pServerName, // ServerName Local version
|
|||
|
name, // MessageName
|
|||
|
level, // level
|
|||
|
&InfoStruct); // buffer pointer
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
DisplayStatus((LPBYTE)InfoStruct, level);
|
|||
|
}
|
|||
|
else {
|
|||
|
printf("[msg] NetMessageNameGetInfo FAILED, rc = %ld\n", status);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else if (_wcsicmp (FixArgv[argIndex], L"add") == 0) {
|
|||
|
|
|||
|
if (argc < argIndex+2) {
|
|||
|
printf("ERROR: no name given for add (msg add <name>)\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(name, FixArgv[argIndex+1]);
|
|||
|
|
|||
|
status = NetMessageNameAdd (
|
|||
|
pServerName, // ServerName Local version
|
|||
|
name); // Name to add
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
printf("name added successfully\n");
|
|||
|
}
|
|||
|
else {
|
|||
|
printf("[msg] NetMessageNameAdd FAILED, rc = %ld\n", status);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else if (_wcsicmp (FixArgv[argIndex], L"del") == 0) {
|
|||
|
|
|||
|
if (argc < argIndex+2) {
|
|||
|
printf("ERROR: no name given for add (msg add <name>)\n");
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
wcscpy(name, FixArgv[argIndex+1]);
|
|||
|
|
|||
|
status = NetMessageNameDel (
|
|||
|
pServerName, // ServerName Local version
|
|||
|
name); // Name to add
|
|||
|
|
|||
|
if (status == NERR_Success) {
|
|||
|
printf("name deleted successfully\n");
|
|||
|
}
|
|||
|
else {
|
|||
|
printf("[msg] NetMessageNameDel FAILED, rc = %ld\n", status);
|
|||
|
}
|
|||
|
}
|
|||
|
|
|||
|
else {
|
|||
|
printf("[msg] Unrecognized Command\n");
|
|||
|
}
|
|||
|
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
/****************************************************************************/
|
|||
|
VOID
|
|||
|
DisplayStatus (
|
|||
|
IN LPBYTE InfoStruct,
|
|||
|
IN DWORD level
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
Displays the returned info buffer.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
InfoStruct2 - This is a pointer to a SERVICE_INFO_2 structure from which
|
|||
|
information is to be displayed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
none.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
LPMSG_INFO_0 InfoStruct0;
|
|||
|
LPMSG_INFO_1 InfoStruct1;
|
|||
|
|
|||
|
switch(level) {
|
|||
|
case 0:
|
|||
|
InfoStruct0 = (LPMSG_INFO_0)InfoStruct;
|
|||
|
printf("\nNAME: %ws\n", InfoStruct0->msgi0_name);
|
|||
|
break;
|
|||
|
case 1:
|
|||
|
InfoStruct1 = (LPMSG_INFO_1)InfoStruct;
|
|||
|
|
|||
|
printf("\nNAME: %ws\n", InfoStruct1->msgi1_name);
|
|||
|
printf(" FWD_FLAG: %ld\n", InfoStruct1->msgi1_forward_flag);
|
|||
|
printf(" FWD_STRING: %ws\n", InfoStruct1->msgi1_forward );
|
|||
|
break;
|
|||
|
default:
|
|||
|
printf("DisplayStatus: illegal level\n");
|
|||
|
}
|
|||
|
return;
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
MakeArgsUnicode (
|
|||
|
DWORD argc,
|
|||
|
PUCHAR argv[]
|
|||
|
)
|
|||
|
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
|
|||
|
Note:
|
|||
|
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
DWORD i;
|
|||
|
|
|||
|
//
|
|||
|
// ScConvertToUnicode allocates storage for each string.
|
|||
|
// We will rely on process termination to free the memory.
|
|||
|
//
|
|||
|
for(i=0; i<argc; i++) {
|
|||
|
|
|||
|
if(!ConvertToUnicode( (LPWSTR *)&(argv[i]), argv[i])) {
|
|||
|
printf("Couldn't convert argv[%d] to unicode\n",i);
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
|
|||
|
}
|
|||
|
return(TRUE);
|
|||
|
}
|
|||
|
|
|||
|
BOOL
|
|||
|
ConvertToUnicode(
|
|||
|
OUT LPWSTR *UnicodeOut,
|
|||
|
IN LPSTR AnsiIn
|
|||
|
)
|
|||
|
|
|||
|
/*++
|
|||
|
|
|||
|
Routine Description:
|
|||
|
|
|||
|
This function translates an AnsiString into a Unicode string.
|
|||
|
A new string buffer is created by this function. If the call to
|
|||
|
this function is successful, the caller must take responsibility for
|
|||
|
the unicode string buffer that was allocated by this function.
|
|||
|
The allocated buffer should be free'd with a call to LocalFree.
|
|||
|
|
|||
|
NOTE: This function allocates memory for the Unicode String.
|
|||
|
|
|||
|
Arguments:
|
|||
|
|
|||
|
AnsiIn - This is a pointer to an ansi string that is to be converted.
|
|||
|
|
|||
|
UnicodeOut - This is a pointer to a location where the pointer to the
|
|||
|
unicode string is to be placed.
|
|||
|
|
|||
|
Return Value:
|
|||
|
|
|||
|
TRUE - The conversion was successful.
|
|||
|
|
|||
|
FALSE - The conversion was unsuccessful. In this case a buffer for
|
|||
|
the unicode string was not allocated.
|
|||
|
|
|||
|
--*/
|
|||
|
{
|
|||
|
|
|||
|
NTSTATUS ntStatus;
|
|||
|
DWORD bufSize;
|
|||
|
UNICODE_STRING unicodeString;
|
|||
|
OEM_STRING ansiString;
|
|||
|
|
|||
|
//
|
|||
|
// Allocate a buffer for the unicode string.
|
|||
|
//
|
|||
|
|
|||
|
bufSize = (strlen(AnsiIn)+1) * sizeof(WCHAR);
|
|||
|
|
|||
|
*UnicodeOut = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, bufSize);
|
|||
|
|
|||
|
if (*UnicodeOut == NULL) {
|
|||
|
printf("ScConvertToUnicode:LocalAlloc Failure %ld\n",GetLastError());
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Initialize the string structures
|
|||
|
//
|
|||
|
NetpInitOemString( &ansiString, AnsiIn);
|
|||
|
|
|||
|
unicodeString.Buffer = *UnicodeOut;
|
|||
|
unicodeString.MaximumLength = (USHORT)bufSize;
|
|||
|
unicodeString.Length = 0;
|
|||
|
|
|||
|
//
|
|||
|
// Call the conversion function.
|
|||
|
//
|
|||
|
ntStatus = RtlOemStringToUnicodeString (
|
|||
|
&unicodeString, // Destination
|
|||
|
&ansiString, // Source
|
|||
|
FALSE); // Allocate the destination
|
|||
|
|
|||
|
if (!NT_SUCCESS(ntStatus)) {
|
|||
|
|
|||
|
printf("ScConvertToUnicode:RtlOemStringToUnicodeString Failure %lx\n",
|
|||
|
ntStatus);
|
|||
|
|
|||
|
return(FALSE);
|
|||
|
}
|
|||
|
|
|||
|
//
|
|||
|
// Fill in the pointer location with the unicode string buffer pointer.
|
|||
|
//
|
|||
|
*UnicodeOut = unicodeString.Buffer;
|
|||
|
|
|||
|
return(TRUE);
|
|||
|
|
|||
|
}
|
|||
|
|