Source code of Windows XP (NT5)
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

472 lines
11 KiB

  1. /*++
  2. Copyright (c) 1990-1992 Microsoft Corporation
  3. Module Name:
  4. MSG.C
  5. Abstract:
  6. Test Routines for the Service Controller.
  7. Author:
  8. Dan Lafferty (danl) 08-May-1991
  9. Environment:
  10. User Mode - Win32
  11. Revision History:
  12. 08-May-1991 danl
  13. created
  14. --*/
  15. //
  16. // INCLUDES
  17. //
  18. #include <nt.h> // DbgPrint prototype
  19. #include <ntrtl.h> // DbgPrint prototype
  20. #include <nturtl.h> // needed for winbase.h
  21. #include <stdlib.h> // atoi
  22. #include <stdio.h> // printf
  23. #include <string.h> // strcmp
  24. #include <windows.h> // win32 typedefs
  25. #include <lmerr.h> // NERR_ error codes
  26. #include <windef.h> // win32 typedefs
  27. #include <lmcons.h>
  28. #include <lmmsg.h>
  29. #include <tstring.h> // Unicode
  30. //
  31. // FUNCTION PROTOTYPES
  32. //
  33. VOID
  34. DisplayStatus (
  35. IN LPBYTE InfoStruct2,
  36. IN DWORD level
  37. );
  38. BOOL
  39. ConvertToUnicode(
  40. OUT LPWSTR *UnicodeOut,
  41. IN LPSTR AnsiIn
  42. );
  43. BOOL
  44. MakeArgsUnicode (
  45. DWORD argc,
  46. PUCHAR argv[]
  47. );
  48. /****************************************************************************/
  49. VOID __cdecl
  50. main (
  51. int argc,
  52. PUCHAR argvA[]
  53. )
  54. /*++
  55. Routine Description:
  56. Allows manual testing of the Messenger Service by typing commands on
  57. the command line such as:
  58. msg add danl - adds a name (danl).
  59. msg del danl - deletes a name (danl).
  60. msg enum - enumerates the names (level 1)
  61. msg enum -l1 - enumerates the names (level 1)
  62. msg enum -l0 - enumerates the names (level 0)
  63. msg enum rh= 2 - enum with resume handle =2 (level1)
  64. msg enum maxlen= 50 - Does an enum with a 50 byte buffer.
  65. msg query danl - gets info on danl. (level 1)
  66. msg query danl -l0 - gets info on danl. (level 0)
  67. Arguments:
  68. Return Value:
  69. --*/
  70. {
  71. NET_API_STATUS status;
  72. LPBYTE InfoStruct;
  73. DWORD entriesRead;
  74. DWORD totalEntries;
  75. DWORD resumeHandle;
  76. DWORD prefMaxLen;
  77. DWORD level;
  78. DWORD specialFlag = FALSE;
  79. DWORD i;
  80. WCHAR name[50];
  81. LPWSTR *argv;
  82. LPWSTR pServerName;
  83. LPTSTR *FixArgv;
  84. INT argIndex;
  85. if (argc <2) {
  86. printf("ERROR: no command was given! (add, del, enum, query)\n");
  87. return;
  88. }
  89. //
  90. // Make the arguments unicode if necessary.
  91. //
  92. argv = (LPWSTR *)argvA;
  93. #ifdef UNICODE
  94. if (!MakeArgsUnicode(argc, (PUCHAR *)argv)) {
  95. return;
  96. }
  97. #endif
  98. FixArgv = (LPTSTR *)argv;
  99. pServerName = NULL;
  100. argIndex = 1;
  101. if (STRNCMP (FixArgv[1], TEXT("\\\\"), 2) == 0) {
  102. pServerName = FixArgv[1];
  103. argIndex = 2;
  104. }
  105. if (_wcsicmp (FixArgv[argIndex], L"enum" ) == 0 ) {
  106. resumeHandle = 0;
  107. level = 1;
  108. prefMaxLen = 0xffffffff;
  109. if (argc > argIndex+1) {
  110. if (_wcsicmp (FixArgv[argIndex+1], L"rh=") == 0) {
  111. specialFlag = TRUE;
  112. if (argc > argIndex+2) {
  113. resumeHandle = wtol(FixArgv[argIndex+2]);
  114. }
  115. }
  116. if (_wcsicmp (FixArgv[argIndex+1], L"-l0") == 0) {
  117. specialFlag = TRUE;
  118. level = 0;
  119. }
  120. if (_wcsicmp (FixArgv[argIndex+1], L"-l2") == 0) {
  121. specialFlag = TRUE;
  122. level = 2;
  123. }
  124. if (_wcsicmp (FixArgv[argIndex+1], L"-l3") == 0) {
  125. specialFlag = TRUE;
  126. level = 3;
  127. }
  128. if (_wcsicmp (FixArgv[argIndex+1], L"maxlen=") == 0) {
  129. specialFlag = TRUE;
  130. if (argc > argIndex+2) {
  131. prefMaxLen = wtol(FixArgv[argIndex+2]);
  132. }
  133. }
  134. }
  135. if ( (argc < argIndex+2) ||
  136. (specialFlag == TRUE) && (argc < argIndex+4) ) {
  137. status = NetMessageNameEnum (
  138. pServerName, // ServerName - Local version
  139. level, // Level
  140. &InfoStruct, // return status buffer pointer
  141. prefMaxLen, // preferred max length
  142. &entriesRead, // entries read
  143. &totalEntries, // total entries
  144. &resumeHandle); // resume handle
  145. if ( (status == NERR_Success) ||
  146. (status == ERROR_MORE_DATA) ){
  147. printf("Enum: entriesRead = %d\n", entriesRead);
  148. printf("Enum: totalEntries = %d\n", totalEntries);
  149. printf("Enum: resumeHandle = %d\n", resumeHandle);
  150. for (i=0; i<entriesRead; i++) {
  151. DisplayStatus(InfoStruct,level);
  152. switch(level) {
  153. case 0:
  154. InfoStruct += sizeof(MSG_INFO_0);
  155. break;
  156. case 1:
  157. InfoStruct += sizeof(MSG_INFO_1);
  158. break;
  159. default:
  160. printf("Bad InfoLevel\n");
  161. }
  162. }
  163. }
  164. else {
  165. printf("[msg] NetServiceEnum FAILED, rc = %ld\n", status);
  166. if (InfoStruct != NULL) {
  167. DisplayStatus(InfoStruct,level);
  168. }
  169. }
  170. }
  171. }
  172. else if (_wcsicmp (FixArgv[argIndex], L"query") == 0) {
  173. level = 1;
  174. if (argc > argIndex+1 ) {
  175. wcscpy(name, FixArgv[argIndex+1]);
  176. }
  177. if (argc > argIndex+2) {
  178. if (_wcsicmp (FixArgv[argIndex+2], TEXT("-l0")) ==0) {
  179. level = 0;
  180. }
  181. }
  182. status = NetMessageNameGetInfo (
  183. pServerName, // ServerName Local version
  184. name, // MessageName
  185. level, // level
  186. &InfoStruct); // buffer pointer
  187. if (status == NERR_Success) {
  188. DisplayStatus((LPBYTE)InfoStruct, level);
  189. }
  190. else {
  191. printf("[msg] NetMessageNameGetInfo FAILED, rc = %ld\n", status);
  192. }
  193. }
  194. else if (_wcsicmp (FixArgv[argIndex], L"add") == 0) {
  195. if (argc < argIndex+2) {
  196. printf("ERROR: no name given for add (msg add <name>)\n");
  197. return;
  198. }
  199. wcscpy(name, FixArgv[argIndex+1]);
  200. status = NetMessageNameAdd (
  201. pServerName, // ServerName Local version
  202. name); // Name to add
  203. if (status == NERR_Success) {
  204. printf("name added successfully\n");
  205. }
  206. else {
  207. printf("[msg] NetMessageNameAdd FAILED, rc = %ld\n", status);
  208. }
  209. }
  210. else if (_wcsicmp (FixArgv[argIndex], L"del") == 0) {
  211. if (argc < argIndex+2) {
  212. printf("ERROR: no name given for add (msg add <name>)\n");
  213. return;
  214. }
  215. wcscpy(name, FixArgv[argIndex+1]);
  216. status = NetMessageNameDel (
  217. pServerName, // ServerName Local version
  218. name); // Name to add
  219. if (status == NERR_Success) {
  220. printf("name deleted successfully\n");
  221. }
  222. else {
  223. printf("[msg] NetMessageNameDel FAILED, rc = %ld\n", status);
  224. }
  225. }
  226. else {
  227. printf("[msg] Unrecognized Command\n");
  228. }
  229. return;
  230. }
  231. /****************************************************************************/
  232. VOID
  233. DisplayStatus (
  234. IN LPBYTE InfoStruct,
  235. IN DWORD level
  236. )
  237. /*++
  238. Routine Description:
  239. Displays the returned info buffer.
  240. Arguments:
  241. InfoStruct2 - This is a pointer to a SERVICE_INFO_2 structure from which
  242. information is to be displayed.
  243. Return Value:
  244. none.
  245. --*/
  246. {
  247. LPMSG_INFO_0 InfoStruct0;
  248. LPMSG_INFO_1 InfoStruct1;
  249. switch(level) {
  250. case 0:
  251. InfoStruct0 = (LPMSG_INFO_0)InfoStruct;
  252. printf("\nNAME: %ws\n", InfoStruct0->msgi0_name);
  253. break;
  254. case 1:
  255. InfoStruct1 = (LPMSG_INFO_1)InfoStruct;
  256. printf("\nNAME: %ws\n", InfoStruct1->msgi1_name);
  257. printf(" FWD_FLAG: %ld\n", InfoStruct1->msgi1_forward_flag);
  258. printf(" FWD_STRING: %ws\n", InfoStruct1->msgi1_forward );
  259. break;
  260. default:
  261. printf("DisplayStatus: illegal level\n");
  262. }
  263. return;
  264. }
  265. BOOL
  266. MakeArgsUnicode (
  267. DWORD argc,
  268. PUCHAR argv[]
  269. )
  270. /*++
  271. Routine Description:
  272. Arguments:
  273. Return Value:
  274. Note:
  275. --*/
  276. {
  277. DWORD i;
  278. //
  279. // ScConvertToUnicode allocates storage for each string.
  280. // We will rely on process termination to free the memory.
  281. //
  282. for(i=0; i<argc; i++) {
  283. if(!ConvertToUnicode( (LPWSTR *)&(argv[i]), argv[i])) {
  284. printf("Couldn't convert argv[%d] to unicode\n",i);
  285. return(FALSE);
  286. }
  287. }
  288. return(TRUE);
  289. }
  290. BOOL
  291. ConvertToUnicode(
  292. OUT LPWSTR *UnicodeOut,
  293. IN LPSTR AnsiIn
  294. )
  295. /*++
  296. Routine Description:
  297. This function translates an AnsiString into a Unicode string.
  298. A new string buffer is created by this function. If the call to
  299. this function is successful, the caller must take responsibility for
  300. the unicode string buffer that was allocated by this function.
  301. The allocated buffer should be free'd with a call to LocalFree.
  302. NOTE: This function allocates memory for the Unicode String.
  303. Arguments:
  304. AnsiIn - This is a pointer to an ansi string that is to be converted.
  305. UnicodeOut - This is a pointer to a location where the pointer to the
  306. unicode string is to be placed.
  307. Return Value:
  308. TRUE - The conversion was successful.
  309. FALSE - The conversion was unsuccessful. In this case a buffer for
  310. the unicode string was not allocated.
  311. --*/
  312. {
  313. NTSTATUS ntStatus;
  314. DWORD bufSize;
  315. UNICODE_STRING unicodeString;
  316. OEM_STRING ansiString;
  317. //
  318. // Allocate a buffer for the unicode string.
  319. //
  320. bufSize = (strlen(AnsiIn)+1) * sizeof(WCHAR);
  321. *UnicodeOut = (LPWSTR)LocalAlloc(LMEM_ZEROINIT, bufSize);
  322. if (*UnicodeOut == NULL) {
  323. printf("ScConvertToUnicode:LocalAlloc Failure %ld\n",GetLastError());
  324. return(FALSE);
  325. }
  326. //
  327. // Initialize the string structures
  328. //
  329. NetpInitOemString( &ansiString, AnsiIn);
  330. unicodeString.Buffer = *UnicodeOut;
  331. unicodeString.MaximumLength = (USHORT)bufSize;
  332. unicodeString.Length = 0;
  333. //
  334. // Call the conversion function.
  335. //
  336. ntStatus = RtlOemStringToUnicodeString (
  337. &unicodeString, // Destination
  338. &ansiString, // Source
  339. FALSE); // Allocate the destination
  340. if (!NT_SUCCESS(ntStatus)) {
  341. printf("ScConvertToUnicode:RtlOemStringToUnicodeString Failure %lx\n",
  342. ntStatus);
  343. return(FALSE);
  344. }
  345. //
  346. // Fill in the pointer location with the unicode string buffer pointer.
  347. //
  348. *UnicodeOut = unicodeString.Buffer;
  349. return(TRUE);
  350. }