Leaked source code of windows server 2003
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.

810 lines
21 KiB

  1. // Copyright (c) 1998-1999 Microsoft Corporation
  2. /******************************************************************************
  3. *
  4. * CHGPORT.C
  5. *
  6. * Change serial port mapping.
  7. *
  8. *
  9. *
  10. *******************************************************************************/
  11. #include <nt.h>
  12. #include <ntrtl.h>
  13. #include <nturtl.h>
  14. #include <windows.h>
  15. #include <winstaw.h>
  16. #include <assert.h>
  17. #include <stdio.h>
  18. #include <stdlib.h>
  19. #include <utilsub.h>
  20. #include <string.h>
  21. #include <printfoa.h>
  22. #include <locale.h>
  23. #include <winnlsp.h>
  24. #include "chgport.h"
  25. // max length of the locale string
  26. #define MAX_LOCALE_STRING 64
  27. /*
  28. * Global Data
  29. */
  30. WCHAR user_string[MAX_IDS_LEN+1]; // parsed user input
  31. USHORT help_flag = FALSE; // User wants help
  32. USHORT fDelete = FALSE; // delete mapped port
  33. USHORT fquery = FALSE; // query the mapped ports
  34. PCOMNAME pValidNames = NULL; // list of valid com names in registry
  35. TOKMAP ptm[] = {
  36. {L" ", TMFLAG_OPTIONAL, TMFORM_STRING, MAX_IDS_LEN, user_string},
  37. {L"/d", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fDelete},
  38. {L"/?", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &help_flag},
  39. {L"/QUERY", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fquery},
  40. {L"/Q", TMFLAG_OPTIONAL, TMFORM_BOOLEAN, sizeof(USHORT), &fquery},
  41. {0, 0, 0, 0, 0}
  42. };
  43. /*
  44. * Constants
  45. */
  46. #define DOSDEVICE_STRING L"\\DosDevices"
  47. /*
  48. * Local function prototypes.
  49. */
  50. void Usage(BOOLEAN bError);
  51. BOOL DeleteMappedPort(PWCHAR user_string);
  52. BOOL GetPorts(PWCHAR user_string,
  53. PWCHAR pwcSrcPort,
  54. PWCHAR pwcDestPort,
  55. ULONG ulbufsize);
  56. BOOL MapPorts(PWCHAR pwcSrcPort,
  57. PWCHAR pwcDestPort);
  58. void ListSerialPorts();
  59. BOOL IsSerialDevice(PWCHAR pwcName);
  60. ULONG GetNTObjectName(PWCHAR pwcDOSdev,
  61. PWCHAR pwcNTObjName,
  62. ULONG ulbufsize);
  63. ULONG AddComName(PCOMNAME *pComList,
  64. PWCHAR pwcNTName,
  65. PWCHAR pwcDOSName);
  66. void DelComName(PCOMNAME pEntry);
  67. PCOMNAME FindComName(PCOMNAME pComList,
  68. PWCHAR pwcName);
  69. BOOL IsVDMdeviceName(PWCHAR pwcName);
  70. /*******************************************************************************
  71. *
  72. * main
  73. *
  74. ******************************************************************************/
  75. int __cdecl
  76. main(INT argc, CHAR **argv)
  77. {
  78. WCHAR **argvW;
  79. WCHAR wcSrcPort[MAX_PATH], wcDestPort[MAX_PATH];
  80. ULONG ulSrcPort, ulDestPort, rc;
  81. INT i;
  82. WCHAR wszString[MAX_LOCALE_STRING + 1];
  83. setlocale(LC_ALL, ".OCP");
  84. // We don't want LC_CTYPE set the same as the others or else we will see
  85. // garbage output in the localized version, so we need to explicitly
  86. // set it to correct console output code page
  87. _snwprintf(wszString, sizeof(wszString)/sizeof(WCHAR), L".%d", GetConsoleOutputCP());
  88. wszString[sizeof(wszString)/sizeof(WCHAR) - 1] = L'\0';
  89. _wsetlocale(LC_CTYPE, wszString);
  90. SetThreadUILanguage(0);
  91. /*
  92. * Massage the command line.
  93. */
  94. argvW = MassageCommandLine((DWORD)argc);
  95. if (argvW == NULL) {
  96. ErrorPrintf(IDS_ERROR_MALLOC);
  97. return(FAILURE);
  98. }
  99. /*
  100. * parse the cmd line without parsing the program name (argc-1, argv+1)
  101. */
  102. rc = ParseCommandLine(argc-1, argvW+1, ptm, 0);
  103. /*
  104. * Check for error from ParseCommandLine
  105. */
  106. if ( help_flag || (rc && !(rc & PARSE_FLAG_NO_PARMS)) ) {
  107. if ( !help_flag ) {
  108. Usage(TRUE);
  109. return(FAILURE);
  110. } else {
  111. Usage(FALSE);
  112. return(SUCCESS);
  113. }
  114. }
  115. //If we are not Running under Terminal Server, Return Error
  116. if(!AreWeRunningTerminalServices())
  117. {
  118. ErrorPrintf(IDS_ERROR_NOT_TS);
  119. return (FAILURE);
  120. }
  121. if (fDelete) {
  122. DeleteMappedPort(user_string);
  123. } else if (*user_string) {
  124. GetPorts(user_string, wcSrcPort, wcDestPort, MAX_PATH);
  125. MapPorts(wcSrcPort, wcDestPort);
  126. } else { // query the mapped ports
  127. ListSerialPorts();
  128. }
  129. // Free up the list of valid port names
  130. if (pValidNames) {
  131. PCOMNAME pEntry, pPrev;
  132. pEntry = pValidNames;
  133. while (pEntry) {
  134. pPrev = pEntry;
  135. pEntry = pEntry->com_pnext;
  136. DelComName(pPrev);
  137. }
  138. }
  139. return(SUCCESS);
  140. }
  141. /*******************************************************************************
  142. *
  143. * Usage
  144. *
  145. * Output the usage message for this utility.
  146. *
  147. * ENTRY:
  148. * bError (input)
  149. * TRUE if the 'invalid parameter(s)' message should preceed the usage
  150. * message and the output go to stderr; FALSE for no such error
  151. * string and output goes to stdout.
  152. *
  153. * EXIT:
  154. *
  155. *
  156. ******************************************************************************/
  157. void
  158. Usage( BOOLEAN bError )
  159. {
  160. if ( bError ) {
  161. ErrorPrintf(IDS_ERROR_INVALID_PARAMETERS);
  162. }
  163. ErrorPrintf(IDS_HELP_USAGE1);
  164. ErrorPrintf(IDS_HELP_USAGE2);
  165. ErrorPrintf(IDS_HELP_USAGE3);
  166. ErrorPrintf(IDS_HELP_USAGE4);
  167. ErrorPrintf(IDS_HELP_USAGE5);
  168. } /* Usage() */
  169. /*******************************************************************************
  170. *
  171. * DeleteMappedPort
  172. *
  173. * This routine deletes the specified mapped port
  174. *
  175. *
  176. * ENTRY:
  177. * PWCHAR pwcport (In): Pointer to port mapping to delete
  178. *
  179. * EXIT:
  180. * TRUE: port was deleted
  181. * FALSE: error deleting port
  182. *
  183. ******************************************************************************/
  184. BOOL DeleteMappedPort(PWCHAR pwcport)
  185. {
  186. ULONG rc;
  187. PWCHAR pwch;
  188. WCHAR wcbuff[MAX_PATH];
  189. // Check if this a serial device and if it is, remove it
  190. if (!GetNTObjectName(pwcport, wcbuff, sizeof(wcbuff)/sizeof(WCHAR)) &&
  191. IsSerialDevice(wcbuff)) {
  192. if (DefineDosDevice(DDD_REMOVE_DEFINITION,
  193. pwcport,
  194. NULL)) {
  195. return(TRUE);
  196. } else {
  197. rc = GetLastError();
  198. }
  199. } else {
  200. rc = ERROR_FILE_NOT_FOUND;
  201. }
  202. StringDwordErrorPrintf(IDS_ERROR_DEL_PORT_MAPPING, pwcport, rc);
  203. return(FALSE);
  204. }
  205. /*******************************************************************************
  206. *
  207. * GetPorts
  208. *
  209. * This routine converts the string to the source and destination ports
  210. *
  211. *
  212. * ENTRY:
  213. * PWCHAR pwcstring (In): Pointer to user string
  214. * PWCHAR pwcSrcPort (Out): Pointer to return source port
  215. * PWCHAR pwcSrcPort (Out): Pointer to return destination port
  216. * ULONG ulbufsize (In): Size of return buffers
  217. *
  218. * EXIT:
  219. * TRUE: string converted to source and destination ports
  220. * FALSE: error
  221. *
  222. ******************************************************************************/
  223. BOOL GetPorts(PWCHAR pwcstring, PWCHAR pwcSrcPort, PWCHAR pwcDestPort,
  224. ULONG ulbufsize)
  225. {
  226. PWCHAR pwch;
  227. ULONG ulcnt;
  228. BOOL fSawEqual = FALSE;
  229. pwch = pwcstring;
  230. // find next non alphanumeric character
  231. for (ulcnt = 0; pwch[ulcnt] && iswalnum(pwch[ulcnt]); ulcnt++) {
  232. }
  233. // Get the source port
  234. if (pwch[ulcnt] && (ulcnt < ulbufsize)) {
  235. wcsncpy(pwcSrcPort, pwch, ulcnt);
  236. } else {
  237. return(FALSE);
  238. }
  239. pwcSrcPort[ulcnt] = L'\0';
  240. pwch += ulcnt;
  241. // get to destination port
  242. while (*pwch && !iswalnum(*pwch)) {
  243. if (*pwch == L'=') {
  244. fSawEqual = TRUE;
  245. }
  246. pwch++;
  247. }
  248. // If the syntax is OK and there's room in the buffer, copy the dest. port
  249. if (*pwch && fSawEqual && (wcslen(pwch) < ulbufsize)) {
  250. wcscpy(pwcDestPort, pwch);
  251. } else {
  252. return(FALSE);
  253. }
  254. // remove the : if they entered comn:
  255. if (pwch = wcsrchr(pwcSrcPort, L':')) {
  256. *pwch = L'\0';
  257. }
  258. if (pwch = wcsrchr(pwcDestPort, L':')) {
  259. *pwch = L'\0';
  260. }
  261. return(TRUE);
  262. }
  263. /*******************************************************************************
  264. *
  265. * MapPorts
  266. *
  267. * This routine maps the source port number to the destination port.
  268. *
  269. *
  270. * ENTRY:
  271. * PWCHAR pwcSrcPort (In): Source port
  272. * PWCHAR pwcDestPort (In): Destination port
  273. *
  274. * EXIT:
  275. * TRUE: port was mapped
  276. * FALSE: error mapping port
  277. *
  278. ******************************************************************************/
  279. BOOL MapPorts(PWCHAR pwcSrcPort, PWCHAR pwcDestPort)
  280. {
  281. ULONG rc = ERROR_FILE_NOT_FOUND;
  282. WCHAR wcdest[MAX_PATH], wcsrc[MAX_PATH];
  283. // Get the NT name of the destination and make sure it's a serial device
  284. rc = GetNTObjectName(pwcDestPort, wcdest, sizeof(wcdest)/sizeof(WCHAR));
  285. if ((rc == 0) && IsSerialDevice(wcdest))
  286. {
  287. // see if this mapping already exists
  288. if (!GetNTObjectName(pwcSrcPort, wcsrc, sizeof(wcsrc)/sizeof(WCHAR)) &&
  289. !_wcsicmp(wcdest, wcsrc)) {
  290. ErrorPrintf(IDS_ERROR_PORT_MAPPING_EXISTS,
  291. pwcSrcPort,
  292. pwcDestPort);
  293. return(FALSE);
  294. }
  295. if (DefineDosDevice(DDD_RAW_TARGET_PATH,
  296. pwcSrcPort,
  297. wcdest)) {
  298. return(TRUE);
  299. } else {
  300. rc = GetLastError();
  301. }
  302. }
  303. StringDwordErrorPrintf(IDS_ERROR_CREATE_PORT_MAPPING, pwcSrcPort, rc);
  304. return(FALSE);
  305. }
  306. /*******************************************************************************
  307. *
  308. * GetNTObjectName
  309. *
  310. * This routine returns the NT object name for a DOS device.
  311. *
  312. * ENTRY:
  313. * PWCHAR pwcDOSdev (In): pointer to DOS device name
  314. * PWCHAR pwcNTObjName (Out): pointer for NT object name
  315. * ULONG ulbufsize (In): size (in wide chars) of object name buffer
  316. *
  317. * EXIT:
  318. * Success:
  319. * returns 0
  320. * Failure:
  321. * returns error code
  322. *
  323. ******************************************************************************/
  324. ULONG GetNTObjectName(PWCHAR pwcDOSdev, PWCHAR pwcNTObjName, ULONG ulbufsize)
  325. {
  326. WCHAR wcbuff[MAX_PATH];
  327. PWCHAR pwch;
  328. // Make a copy of the name passed in
  329. wcscpy(wcbuff, pwcDOSdev);
  330. // Strip off any trailing colon (comn:)
  331. if (pwch = wcsrchr(wcbuff, L':')) {
  332. *pwch = L'\0';
  333. }
  334. if (QueryDosDevice(pwcDOSdev, pwcNTObjName, ulbufsize)) {
  335. return(0);
  336. } else {
  337. return(GetLastError());
  338. }
  339. }
  340. /*******************************************************************************
  341. *
  342. * ListSerialPorts
  343. *
  344. * This routine lists all of the mapped ports.
  345. *
  346. * ENTRY:
  347. *
  348. * EXIT:
  349. *
  350. ******************************************************************************/
  351. void ListSerialPorts(void)
  352. {
  353. ULONG ulcnt, rc;
  354. WCHAR TargetPath[4096];
  355. PWCH pwch;
  356. PCOMNAME pComList = NULL;
  357. PCOMNAME pEntry, pPrev;
  358. DWORD dwBufferSize = 2048;
  359. WCHAR *DeviceNames = malloc(dwBufferSize);
  360. if (!DeviceNames)
  361. {
  362. ErrorPrintf(IDS_ERROR_MALLOC);
  363. free(DeviceNames);
  364. return;
  365. }
  366. //
  367. // Get all of the defined DOS devices
  368. //
  369. //
  370. // QueryDosDevice function returns success even if buffer is too small!
  371. // Lets get around it
  372. //
  373. SetLastError(0);
  374. while ( (!QueryDosDevice(NULL, DeviceNames, dwBufferSize / sizeof(WCHAR))) ||
  375. (GetLastError() == ERROR_INSUFFICIENT_BUFFER) )
  376. {
  377. if (GetLastError() == ERROR_INSUFFICIENT_BUFFER)
  378. {
  379. SetLastError(0);
  380. free(DeviceNames);
  381. dwBufferSize *= 2;
  382. DeviceNames = malloc(dwBufferSize);
  383. if (!DeviceNames)
  384. {
  385. ErrorPrintf(IDS_ERROR_MALLOC);
  386. return;
  387. }
  388. }
  389. else
  390. {
  391. ErrorPrintf(IDS_ERROR_GETTING_COMPORTS, GetLastError());
  392. free(DeviceNames);
  393. return;
  394. }
  395. }
  396. pwch = DeviceNames;
  397. // Go through each DOS device and get it's NT object name, then check if
  398. // it's a serial device, and if so display it
  399. while (*pwch)
  400. {
  401. rc = GetNTObjectName(pwch,
  402. TargetPath,
  403. sizeof(TargetPath)/sizeof(WCHAR));
  404. if (rc)
  405. {
  406. ErrorPrintf(IDS_ERROR_GETTING_COMPORTS, rc);
  407. }
  408. else if (IsSerialDevice(TargetPath))
  409. {
  410. AddComName(&pComList, TargetPath, pwch);
  411. }
  412. pwch += wcslen(pwch) + 1;
  413. }
  414. if (pComList)
  415. {
  416. // print out the entries
  417. pEntry = pComList;
  418. while (pEntry)
  419. {
  420. wprintf(L"%s = %s\n", pEntry->com_pwcDOSName, pEntry->com_pwcNTName);
  421. pPrev = pEntry;
  422. pEntry = pEntry->com_pnext;
  423. DelComName(pPrev);
  424. }
  425. }
  426. else
  427. {
  428. ErrorPrintf(IDS_ERROR_NO_SERIAL_PORTS);
  429. }
  430. free(DeviceNames);
  431. }
  432. /*******************************************************************************
  433. *
  434. * IsSerialDevice
  435. *
  436. * This routine checks if the NT file name is a serial device
  437. *
  438. *
  439. * ENTRY:
  440. * PWCHAR pwcName (In): Pointer to name to check
  441. *
  442. * EXIT:
  443. * TRUE: Is a serial device
  444. * FALSE: Not a serial device
  445. *
  446. ******************************************************************************/
  447. BOOL IsSerialDevice(PWCHAR pwcName)
  448. {
  449. NTSTATUS Status;
  450. HANDLE Handle;
  451. IO_STATUS_BLOCK IoStatusBlock;
  452. FILE_FS_DEVICE_INFORMATION FileFSDevInfo;
  453. OBJECT_ATTRIBUTES ObjFile;
  454. UNICODE_STRING UniFile;
  455. WCHAR wcbuff[MAX_PATH];
  456. WCHAR wcvalue[MAX_PATH];
  457. PWCHAR pwch;
  458. HKEY hKey;
  459. ULONG ulType, ulSize, ulcnt, ulValSize;
  460. BOOL fIsSerial = FALSE;
  461. if (IsVDMdeviceName(pwcName)) {
  462. return FALSE;
  463. }
  464. RtlInitUnicodeString(&UniFile, pwcName);
  465. InitializeObjectAttributes(&ObjFile,
  466. &UniFile,
  467. OBJ_CASE_INSENSITIVE,
  468. NULL,
  469. NULL);
  470. //
  471. // Open the device
  472. //
  473. Status = NtOpenFile(&Handle,
  474. (ACCESS_MASK)FILE_READ_ATTRIBUTES | SYNCHRONIZE,
  475. &ObjFile,
  476. &IoStatusBlock,
  477. FILE_SHARE_READ | FILE_SHARE_WRITE,
  478. FILE_SYNCHRONOUS_IO_NONALERT | FILE_NON_DIRECTORY_FILE);
  479. if (NT_SUCCESS(Status)) {
  480. Status = NtQueryVolumeInformationFile(Handle,
  481. &IoStatusBlock,
  482. &FileFSDevInfo,
  483. sizeof(FileFSDevInfo),
  484. FileFsDeviceInformation);
  485. // Check if this is actually a serial device or not
  486. if (NT_SUCCESS(Status))
  487. {
  488. if ( (FileFSDevInfo.DeviceType == FILE_DEVICE_NETWORK_REDIRECTOR) ||
  489. (FileFSDevInfo.DeviceType == FILE_DEVICE_SERIAL_PORT) )
  490. {
  491. fIsSerial = TRUE;
  492. }
  493. }
  494. // Close the file handle
  495. NtClose(Handle);
  496. } else {
  497. // If we couldn't open the device, look for the name in the registry
  498. #ifdef DEBUG
  499. wprintf(L"Error opening: %s, error = %x\n", pwcName, Status);
  500. #endif
  501. // strip off the leading \device
  502. pwch = wcschr(pwcName+2, L'\\');
  503. if (pwch != NULL)
  504. {
  505. pwch++;
  506. // If we haven't built the list of valid names from the registry,
  507. // build it.
  508. if (pValidNames == NULL) {
  509. // Open the serialcomm entry in the registry
  510. if (RegOpenKeyEx(HKEY_LOCAL_MACHINE,
  511. L"Hardware\\DeviceMap\\SerialComm",
  512. 0,
  513. KEY_READ,
  514. &hKey) == ERROR_SUCCESS) {
  515. ulValSize = ulSize = MAX_PATH;
  516. ulcnt = 0;
  517. // Put all of the valid entries into the valid names list
  518. while (!RegEnumValue (hKey, ulcnt++, wcvalue, &ulValSize,
  519. NULL, &ulType, (LPBYTE) wcbuff, &ulSize))
  520. {
  521. if (ulType != REG_SZ)
  522. continue;
  523. AddComName(&pValidNames, wcvalue, wcbuff);
  524. ulValSize = ulSize = MAX_PATH;
  525. }
  526. RegCloseKey(hKey);
  527. }
  528. }
  529. // look for the name in the list of valid com names
  530. if (FindComName(pValidNames, pwch)) {
  531. fIsSerial = TRUE;
  532. }
  533. }
  534. }
  535. return(fIsSerial);
  536. }
  537. /*****************************************************************************
  538. *
  539. * AddComName
  540. *
  541. * This routines adds a new node onto the specified com port names.
  542. *
  543. * ENTRY:
  544. * PCOMNAME *pComList (In) - Pointer to list to add entry to
  545. * PWCHAR pwcNTName (In) - NT name of device
  546. * PWCHAR pwcDOSName (In) - DOW name of device
  547. *
  548. * EXIT:
  549. * SUCCESS:
  550. * return ERROR_SUCCESS
  551. * FAILURE:
  552. * returns error code
  553. *
  554. ****************************************************************************/
  555. ULONG AddComName(PCOMNAME *pComList,
  556. PWCHAR pwcNTName,
  557. PWCHAR pwcDOSName)
  558. {
  559. PCOMNAME pnext, pprev, pnew;
  560. LONG rc = ERROR_SUCCESS;
  561. if (pnew = malloc(sizeof(COMNAME))) {
  562. // clear out the new entry
  563. memset(pnew, 0, sizeof(COMNAME));
  564. // Allocate and initialize the NT name
  565. if (pnew->com_pwcNTName =
  566. malloc((wcslen(pwcNTName) + 1)*sizeof(WCHAR))) {
  567. wcscpy(pnew->com_pwcNTName, pwcNTName);
  568. } else {
  569. rc = ERROR_NOT_ENOUGH_MEMORY;
  570. }
  571. // Allocate and initialize the DOS name
  572. if ((rc == ERROR_SUCCESS) && (pnew->com_pwcDOSName =
  573. malloc((wcslen(pwcDOSName) + 1)*sizeof(WCHAR)))) {
  574. wcscpy(pnew->com_pwcDOSName, pwcDOSName);
  575. } else {
  576. rc = ERROR_NOT_ENOUGH_MEMORY;
  577. }
  578. } else {
  579. rc = ERROR_NOT_ENOUGH_MEMORY;
  580. }
  581. // If we allocate everything OK, add the node into the list
  582. if (rc == ERROR_SUCCESS) {
  583. pprev = NULL;
  584. pnext = *pComList;
  585. // Insert the entry into the list in ascending order
  586. while (pnext &&
  587. ((rc = _wcsicmp(pwcDOSName, pnext->com_pwcDOSName)) > 0)) {
  588. pprev = pnext;
  589. pnext = pnext->com_pnext;
  590. }
  591. // just return if this name is already in the list
  592. if (pnext && (rc == 0)) {
  593. return(ERROR_SUCCESS);
  594. }
  595. // Insert this entry into the list
  596. pnew->com_pnext = pnext;
  597. // If this is going to the front of the list, update list pointer
  598. if (pprev == NULL) {
  599. *pComList = pnew;
  600. } else {
  601. pprev->com_pnext = pnew;
  602. }
  603. } else if (pnew) {
  604. // Didn't allocate everything, release the memory we got
  605. DelComName(pnew);
  606. }
  607. return(rc);
  608. }
  609. /*****************************************************************************
  610. *
  611. * DelComName
  612. *
  613. * This routines frees up the memory allocated to a com name node.
  614. *
  615. * ENTRY:
  616. * PCOMNAME pEntry (In) - Node to delete
  617. *
  618. * EXIT:
  619. * NONE
  620. *
  621. ****************************************************************************/
  622. void DelComName(PCOMNAME pEntry)
  623. {
  624. if (pEntry) {
  625. if (pEntry->com_pwcNTName) {
  626. free(pEntry->com_pwcNTName);
  627. }
  628. if (pEntry->com_pwcDOSName) {
  629. free(pEntry->com_pwcDOSName);
  630. }
  631. free(pEntry);
  632. }
  633. }
  634. /*****************************************************************************
  635. *
  636. * FindComName
  637. *
  638. * This routines searches for the specified name in the com port list.
  639. *
  640. * ENTRY:
  641. * PCOMNAME pComList (In) - List to search
  642. * PWCHAR pwcName (In) - Name to search for
  643. *
  644. * EXIT:
  645. * SUCCESS:
  646. * returns pointer to node containing the specified name
  647. * FAILURE:
  648. * returns NULL (name not found)
  649. *
  650. ****************************************************************************/
  651. PCOMNAME FindComName(PCOMNAME pComList,
  652. PWCHAR pwcName)
  653. {
  654. PCOMNAME pcom;
  655. pcom = pComList;
  656. while (pcom) {
  657. //Check if the name matches either the NT or DOS device name
  658. if (!_wcsicmp(pwcName, pcom->com_pwcDOSName) ||
  659. !_wcsicmp(pwcName, pcom->com_pwcNTName)) {
  660. return(pcom);
  661. }
  662. pcom = pcom->com_pnext;
  663. }
  664. return(NULL);
  665. }
  666. BOOL IsVDMdeviceName(PWCHAR pwcName)
  667. {
  668. UINT index;
  669. UINT vdmlength = wcslen(L"VDM");
  670. for (index = 0; (index+vdmlength-1) < wcslen(pwcName); index++) {
  671. if (_wcsnicmp(&pwcName[index], L"VDM", vdmlength) == 0) {
  672. return TRUE;
  673. }
  674. }
  675. return FALSE;
  676. }
  677.