|
|
1.1 ! root 1: /****************************************************************************\ ! 2: * ! 3: * MODULE: winnet.c ! 4: * ! 5: * PURPOSE: Demonstrate the WNetXXX Win32 api(s) (10 of the 11 - all but ! 6: * WNetConnectionDialog are demonstrated) ! 7: * ! 8: * TO RUN: Ensure 1 or more network disk shares can be used by the ! 9: * machine/user-id you run winnet on, and that these 1 or more ! 10: * network disk shares aren't already connected to the ! 11: * machine/user-id you run winnet on. These net shares must ! 12: * not require a password ! 13: * ! 14: * IMPORTANT: Ensure W: is not in use when you type "WINNET" ! 15: * ! 16: * OVERALL APPROACH: Find a connectable disk resource on the network, connect ! 17: * to it, and disconnect ! 18: * ! 19: * The first time you run this sample, it's probably best to ! 20: * ensure there's a shared disk directory accessable to the ! 21: * machine on which you run this program, so you can see the ! 22: * success paths in this code exercised first. Ensure this ! 23: * shared disk is NOT already connected ! 24: * ! 25: * We recursively open containers returned by the EnumResources ! 26: * calls (recursively using OpenEnum), but will bail out of the ! 27: * recursion without fully exploring all containers and enum's ! 28: * if we hit the arbitrary limit placed on how many connectable ! 29: * disk resources we enter into our list. Since there may ! 30: * possibly be many more enumerable resources on a net than ! 31: * there are connectable disk resources, we also place another ! 32: * arbitrary limit on the total number of resources we'll ! 33: * enumerate ! 34: * ! 35: * Both limits can easily be removed or raised by anyone working ! 36: * with this sample code ! 37: * ! 38: * After the container exploration is completed, we walk down the ! 39: * list of connectable disk resources, arbitrarily picking one ! 40: * to connect to and then disconnect from ! 41: * ! 42: * FUNCTIONS: Open_Do_Close_1_Enum ! 43: * ! 44: * Called by main with a NULL container to start the enumeration ! 45: * of the top-level container. Called recursively from ! 46: * EnumResources ! 47: * ! 48: * OpenEnum ! 49: * ! 50: * Returns an enumeration handle by opening a container ! 51: * ! 52: * EnumResources ! 53: * ! 54: * Enumerates the connectable resources and containers, given an ! 55: * enumeration handle. Recusively calls Open_Do_Close_1_Enum ! 56: * ! 57: * AddGetGetCancel ! 58: * AddGetGetCancel2 ! 59: * ! 60: * Identical logic in both functions adds a connection, gets the ! 61: * user for the connection, gets information about the ! 62: * connection and then cancels the connection. The difference ! 63: * is that AddGetGetCancel2 uses the new Win32 forms of the Add ! 64: * and Cancel api's ! 65: * ! 66: * PrintAPIError ! 67: * ! 68: * Simple routine to print error message info ! 69: * ! 70: * GLOBAL VARS: ! 71: * ConnectablesList ! 72: * ! 73: * List of disk resources we can connect to. Filled in while ! 74: * enumeration resources, walked after all enumeration is ! 75: * complete ! 76: * ! 77: * dwResourcesEnumedSoFar ! 78: * ! 79: * Counter of resources enumerated so far, includes count of both ! 80: * disk resources and containers enumerated. If many ! 81: * containers are enumerated compared to disk resources, this ! 82: * counter will limit the search. If many disk resources are ! 83: * found compared to containers, the size of ConnectablesList ! 84: * will limit the search ! 85: * ! 86: * dwDiskListI ! 87: * ! 88: * Index into ConnectablesList. At all times, except when adding ! 89: * a list entry, dwDiskListI is 1 greater than the number of ! 90: * entries we have entered into ConnectablesList ! 91: * ! 92: \****************************************************************************/ ! 93: ! 94: ! 95: /****************************************************************************\ ! 96: * INCLUDES, DEFINES, TYPEDEFS ! 97: \****************************************************************************/ ! 98: #define STRICT ! 99: #include <windows.h> ! 100: #include <stdio.h> ! 101: #include <string.h> ! 102: #include <stdlib.h> ! 103: #include <winnetwk.h> ! 104: ! 105: #define PERR(api) printf("%s: Error %d from %s on line %d\n", \ ! 106: __FILE__, GetLastError(), api, __LINE__); ! 107: #define PMSG(msg) printf("%s line %d: %s\n", \ ! 108: __FILE__, __LINE__, msg); ! 109: ! 110: #define PrintAppStyleAPIError(ApiTxt,MsgTxt) { \ ! 111: PrintAPIError( #ApiTxt , #MsgTxt , __LINE__ , __FILE__ ); \ ! 112: } ! 113: ! 114: ! 115: /****************************************************************************\ ! 116: * ! 117: * These next two search limits are completely tunable. On one net ! 118: * MAX_NUMBER_OF_RESOURCES_TO_ENUM had to be 2200 to see 3 or 4 sharable disk ! 119: * resources. This could vary widely depending on the number of servers on ! 120: * the net that have no shares up ! 121: * ! 122: \****************************************************************************/ ! 123: ! 124: #define MAX_NUMBER_OF_DISK_RESOURCES_TO_LIST 3 ! 125: #define MAX_NUMBER_OF_RESOURCES_TO_ENUM 2200 ! 126: ! 127: #define LOCAL_DEVICE_NAME "W:" ! 128: #define WHICH_TO_USE_FROM_LIST 0 ! 129: ! 130: typedef struct _DISK_RESOURCES_CONNECTABLE ! 131: { ! 132: LPTSTR lpRemoteName; ! 133: LPTSTR lpComment; ! 134: LPTSTR lpProvider; ! 135: } DISK_RESOURCES_CONNECTABLE, *LPDISK_RESOURCES_CONNECTABLE; ! 136: ! 137: /****************************************************************************\ ! 138: * GLOBAL VARIABLES ! 139: \****************************************************************************/ ! 140: ! 141: DISK_RESOURCES_CONNECTABLE ! 142: ConnectablesList[MAX_NUMBER_OF_DISK_RESOURCES_TO_LIST]; ! 143: DWORD dwResourcesEnumedSoFar = 0; ! 144: DWORD dwDiskListI = 0; ! 145: ! 146: /****************************************************************************\ ! 147: * FUNCTION PROTOTYPES ! 148: \****************************************************************************/ ! 149: ! 150: VOID Open_Do_Close_1_Enum(LPNETRESOURCE lpNetContainerToOpen); ! 151: HANDLE OpenEnum (LPNETRESOURCE lpNetContainerToOpen); ! 152: UINT EnumResources(HANDLE hNetEnum); ! 153: VOID AddGetGetCancel(VOID); ! 154: VOID AddGetGetCancel2(VOID); ! 155: VOID PrintAPIError(LPTSTR ApiTxt, ! 156: LPTSTR MsgTxt, ! 157: UINT Line, ! 158: LPTSTR File); ! 159: ! 160: /****************************************************************************\ ! 161: * ! 162: * FUNCTION: Main ! 163: * ! 164: \****************************************************************************/ ! 165: ! 166: UINT main(UINT argc, char *argv[]) ! 167: { ! 168: UNREFERENCED_PARAMETER(argv[1]); ! 169: ! 170: if (argc > 1) ! 171: { printf("\nTo run type 'winnet', with no parameters\n"); ! 172: printf("\n IMPORTANT: Ensure W: is not in use when you type WINNET\n"); ! 173: return(1); ! 174: } ! 175: ! 176: /**************************************************************************\ ! 177: * ! 178: * Pass NULL as container argument to get top level container. This call ! 179: * starts the recursive exploration of the top level network resource ! 180: * container ! 181: * ! 182: \**************************************************************************/ ! 183: ! 184: Open_Do_Close_1_Enum(NULL); ! 185: ! 186: /**************************************************************************\ ! 187: * ! 188: * We now have a list of connectable resources in our table, but some error ! 189: * conditions may have caused the list to be 0 length ! 190: * ! 191: \**************************************************************************/ ! 192: ! 193: if (0<dwDiskListI) ! 194: { AddGetGetCancel(); ! 195: AddGetGetCancel2(); ! 196: } ! 197: else ! 198: { printf("\nError: enumerated 0 connectable disk resources!\n"); ! 199: } ! 200: ! 201: /**************************************************************************\ ! 202: * ! 203: * Free the list of connectable resources, zero length or not ! 204: * ! 205: \**************************************************************************/ ! 206: ! 207: { DWORD i; ! 208: for (i=0; i<dwDiskListI; i++) ! 209: { ! 210: free(ConnectablesList[i].lpRemoteName); ! 211: free(ConnectablesList[i].lpComment ); ! 212: free(ConnectablesList[i].lpProvider ); ! 213: } ! 214: } ! 215: ! 216: return(0); ! 217: } ! 218: ! 219: /****************************************************************************\ ! 220: * ! 221: * FUNCTION: Open_Do_Close_1_Enum ! 222: * ! 223: * COMMENTS: There's little reason this is in a separate function in this ! 224: * sample other than the code is used in two places, so putting it ! 225: * in a separate function saves repetition in the source code ! 226: * ! 227: \****************************************************************************/ ! 228: ! 229: VOID Open_Do_Close_1_Enum(LPNETRESOURCE lpNetContainerToOpen) ! 230: { ! 231: HANDLE hNetEnum; ! 232: ! 233: hNetEnum = OpenEnum(lpNetContainerToOpen); ! 234: ! 235: if (!hNetEnum) ! 236: return; ! 237: ! 238: if (!EnumResources(hNetEnum)) ! 239: return; ! 240: ! 241: if (NO_ERROR != WNetCloseEnum(hNetEnum)) ! 242: { PERR("WNetCloseEnum"); ! 243: return; ! 244: } ! 245: } ! 246: ! 247: /****************************************************************************\ ! 248: * ! 249: * FUNCTION: OpenEnum ! 250: * ! 251: \****************************************************************************/ ! 252: ! 253: HANDLE OpenEnum(LPNETRESOURCE lpNetContainerToOpen) ! 254: { ! 255: HANDLE hNetEnum; ! 256: ! 257: if (NO_ERROR != WNetOpenEnum(RESOURCE_GLOBALNET, ! 258: RESOURCETYPE_DISK, ! 259: (RESOURCEUSAGE_CONNECTABLE | RESOURCEUSAGE_CONTAINER), ! 260: lpNetContainerToOpen, ! 261: (LPHANDLE)&hNetEnum)) ! 262: { if (GetLastError() != NO_ERROR) ! 263: { PrintAppStyleAPIError(WNetOpenEnum,"OpenEnum"); ! 264: return(NULL); ! 265: } ! 266: } ! 267: ! 268: return(hNetEnum); ! 269: } ! 270: ! 271: /****************************************************************************\ ! 272: * ! 273: * FUNCTION: EnumResources ! 274: * ! 275: \****************************************************************************/ ! 276: ! 277: UINT EnumResources(HANDLE hNetEnum) ! 278: { ! 279: #define RESOURCE_BUF_ENTRIES 500 ! 280: NETRESOURCE ResourceBuffer[RESOURCE_BUF_ENTRIES]; // about 13K for 500 ! 281: DWORD dwSzResourceBuf; ! 282: DWORD dwEntriesToGet; ! 283: ! 284: /**************************************************************************\ ! 285: * ! 286: * It's possible that not all entries will fit in a RESOURCE_BUF_ENTRIES slot ! 287: * buffer, so we call WNetEnumResource in a loop, asking for ! 288: * RESOURCE_BUF_ENTRIES at a time, and continuing to call WNetEnumResource ! 289: * until it returns no more entries ! 290: * ! 291: \**************************************************************************/ ! 292: ! 293: for (;;) ! 294: { ! 295: dwSzResourceBuf = sizeof(ResourceBuffer); ! 296: dwEntriesToGet = RESOURCE_BUF_ENTRIES; ! 297: ! 298: printf("Getting %d entries\n",dwEntriesToGet); ! 299: ! 300: if (NO_ERROR != WNetEnumResource(hNetEnum, ! 301: (LPDWORD)&dwEntriesToGet, ! 302: (LPVOID)ResourceBuffer, ! 303: (LPDWORD)&dwSzResourceBuf)) ! 304: { switch (GetLastError()) ! 305: { case NO_ERROR : ! 306: // Drop out of the switch, walk the buffer ! 307: break; ! 308: case ERROR_NO_MORE_ITEMS : ! 309: // Return with 0 code because this only happens when we got ! 310: // RESOURCE_BUF_ENTRIES entries on the previous call to ! 311: // WNetEnumResource, and there were coincidentally exactly ! 312: // RESOURCE_BUF_ENTRIES entries total in the enum at the time of ! 313: // that previous call ! 314: return(0); ! 315: default : ! 316: PrintAppStyleAPIError(WNetEnumResource,"EnumResources"); ! 317: return(1); ! 318: } ! 319: } ! 320: ! 321: /************************************************************************\ ! 322: * ! 323: * Walk the returned buffer. Now dwEntriesToGet has been set by the api ! 324: * call to be the number of entries actually returned ! 325: * ! 326: \************************************************************************/ ! 327: ! 328: { ! 329: DWORD i; ! 330: ! 331: printf("Got %d entries\n",dwEntriesToGet); ! 332: ! 333: for (i=0; i<dwEntriesToGet; i++) ! 334: { ! 335: printf("\nResourceBuffer[%d].dwScope = 0x%x \n",i, ! 336: ResourceBuffer[i].dwScope); ! 337: printf("ResourceBuffer[%d].dwType = 0x%x \n",i, ! 338: ResourceBuffer[i].dwType); ! 339: printf("ResourceBuffer[%d].dwUsage = 0x%x \n",i, ! 340: ResourceBuffer[i].dwUsage); ! 341: printf("ResourceBuffer[%d].lpLocalName = %s \n",i, ! 342: ResourceBuffer[i].lpLocalName); ! 343: printf("ResourceBuffer[%d].lpRemoteName = %s \n",i, ! 344: ResourceBuffer[i].lpRemoteName); ! 345: printf("ResourceBuffer[%d].lpComment = %s \n",i, ! 346: ResourceBuffer[i].lpComment); ! 347: printf("ResourceBuffer[%d].lpProvider = %s \n",i, ! 348: ResourceBuffer[i].lpProvider); ! 349: ! 350: dwResourcesEnumedSoFar += dwEntriesToGet; ! 351: ! 352: printf("dwResourcesEnumedSoFar = %d \n",dwResourcesEnumedSoFar); ! 353: ! 354: if (dwDiskListI >= MAX_NUMBER_OF_DISK_RESOURCES_TO_LIST) ! 355: return(0); // List full, stop enumerating ! 356: ! 357: switch (ResourceBuffer[i].dwUsage) ! 358: { case RESOURCEUSAGE_CONNECTABLE : ! 359: ! 360: ConnectablesList [dwDiskListI].lpRemoteName = ! 361: malloc(1+strlen(ResourceBuffer[i].lpRemoteName)); ! 362: ConnectablesList [dwDiskListI].lpComment = ! 363: malloc(1+strlen(ResourceBuffer[i].lpComment )); ! 364: ConnectablesList [dwDiskListI].lpProvider = ! 365: malloc(1+strlen(ResourceBuffer[i].lpProvider )); ! 366: ! 367: if ((NULL == ConnectablesList[dwDiskListI].lpRemoteName) || ! 368: (NULL == ConnectablesList[dwDiskListI].lpComment ) || ! 369: (NULL == ConnectablesList[dwDiskListI].lpProvider )) ! 370: PERR("EnumResource - ran out of heap space"); ! 371: ! 372: strcpy(ConnectablesList[dwDiskListI].lpRemoteName, ! 373: ResourceBuffer[i].lpRemoteName); ! 374: strcpy(ConnectablesList[dwDiskListI].lpComment , ! 375: ResourceBuffer[i].lpComment ); ! 376: strcpy(ConnectablesList[dwDiskListI].lpProvider , ! 377: ResourceBuffer[i].lpProvider ); ! 378: ! 379: dwDiskListI++; ! 380: ! 381: break; ! 382: ! 383: case RESOURCEUSAGE_CONTAINER : // Regular container ! 384: case (RESOURCEUSAGE_CONTAINER | RESOURCEUSAGE_RESERVED) : // Top-level container ! 385: ! 386: /****************************************************************\ ! 387: * ! 388: * This next test is here to filter out servers we don't wish to ! 389: * enumerate while running the sample. A real app would be more ! 390: * likely to look at all servers, but for running a sample, it's ! 391: * worthwhile to think about which servers should actually be ! 392: * enumerated, to avoid annoying people who have other servers on ! 393: * the net they may not wish to be disturbed ! 394: * ! 395: * So, you may want to modify this test to filter out whatever ! 396: * servers make sense to filter out in your environment ! 397: * ! 398: * The first clause shows how to include in the filter the top ! 399: * level NT Lan Man container, the second clause shows how to ! 400: * include in the filter a domain name, and the third and fourth ! 401: * clauses show how to include any servers whose names start with ! 402: * particular characters ! 403: * ! 404: \****************************************************************/ ! 405: ! 406: if (!( (0==strncmp("NT Lan Man",ResourceBuffer[i].lpRemoteName,10)) ! 407: ||(0==strncmp("NtW000",ResourceBuffer[i].lpRemoteName,6)) ! 408: ||(0==strncmp("\\\\BR",ResourceBuffer[i].lpRemoteName,4)) ! 409: ||(0==strncmp("\\\\BL",ResourceBuffer[i].lpRemoteName,4)))) ! 410: break; ! 411: ! 412: if (dwResourcesEnumedSoFar < MAX_NUMBER_OF_RESOURCES_TO_ENUM) ! 413: Open_Do_Close_1_Enum(&ResourceBuffer[i]); ! 414: ! 415: break; ! 416: ! 417: case RESOURCEUSAGE_RESERVED : // Ignore these ! 418: break; ! 419: ! 420: default : ! 421: { UCHAR ucMsgBuf[1500]; ! 422: ! 423: sprintf(ucMsgBuf,"WNetEnumResources bad .dwUsage value = 0x%X,\n", ! 424: ResourceBuffer[i].dwUsage); ! 425: PERR(ucMsgBuf); ! 426: return(1); ! 427: } ! 428: } ! 429: } ! 430: } ! 431: ! 432: /************************************************************************\ ! 433: * ! 434: * We have walked the returned buffer. Since dwEntriesToGet has been set ! 435: * by the api call to be the number of entries actually returned, if how ! 436: * many were returned is less than what we asked for, return out of the ! 437: * loop because this enum is done ! 438: * ! 439: \************************************************************************/ ! 440: ! 441: if (dwEntriesToGet < RESOURCE_BUF_ENTRIES) ! 442: return(0); ! 443: ! 444: } ! 445: PERR("WNetEnumResource - impossible to drop out of infinite loop"); ! 446: return(1); ! 447: } ! 448: ! 449: /****************************************************************************\ ! 450: * ! 451: * FUNCTION: AddGetGetCancel ! 452: * ! 453: * COMMENTS: Connects to first disk resource on our global list ! 454: * ! 455: \****************************************************************************/ ! 456: ! 457: VOID AddGetGetCancel(VOID) ! 458: { ! 459: UCHAR ucLocalName[sizeof(LOCAL_DEVICE_NAME)+1] = LOCAL_DEVICE_NAME; ! 460: UCHAR ucPassword[] = ""; ! 461: #define SZ_BUF 1000 ! 462: UCHAR ucRemoteName[SZ_BUF]; ! 463: UCHAR ucUserName [SZ_BUF]; ! 464: DWORD dwSzBuf = SZ_BUF; ! 465: ! 466: if (NO_ERROR != WNetAddConnection( ! 467: ConnectablesList[WHICH_TO_USE_FROM_LIST].lpRemoteName, ! 468: (LPTSTR)ucPassword,(LPTSTR)ucLocalName)) ! 469: { PrintAppStyleAPIError(WNetAddConnection,"AddGetGetCancel"); ! 470: return; ! 471: } ! 472: ! 473: dwSzBuf = SZ_BUF; ! 474: ! 475: if (NO_ERROR != WNetGetConnection((LPTSTR)ucLocalName, ! 476: (LPTSTR)ucRemoteName,(LPDWORD)&dwSzBuf)) ! 477: { PrintAppStyleAPIError(WNetGetConnection,"AddGetGetCancel"); ! 478: return; ! 479: } ! 480: ! 481: dwSzBuf = SZ_BUF; ! 482: ! 483: if (NO_ERROR != WNetGetUser((LPTSTR)ucLocalName, ! 484: (LPTSTR)ucUserName,(LPDWORD)&dwSzBuf)) ! 485: { PrintAppStyleAPIError(WNetGetUser,"AddGetGetCancel"); ! 486: return; ! 487: } ! 488: ! 489: printf("\nDisk resource AddGetGetCancel connected = [%s], User name logged on to that resource = [%s]\n", ! 490: ucRemoteName,ucUserName); ! 491: ! 492: if (NO_ERROR != WNetCancelConnection((LPTSTR)ucLocalName,FALSE)) ! 493: { PrintAppStyleAPIError(WNetCancelConnection,"AddGetGetCancel"); ! 494: return; ! 495: } ! 496: } ! 497: ! 498: /****************************************************************************\ ! 499: * ! 500: * FUNCTION: AddGetGetCancel2 ! 501: * ! 502: * COMMENTS: If we had chosen to keep our list as a list of NetResource data ! 503: * structures, using the new form of AddConnection2 would have been ! 504: * easier to code. As it is, declaring and filling in the ! 505: * NetResource takes a few more lines ! 506: * ! 507: \****************************************************************************/ ! 508: ! 509: VOID AddGetGetCancel2(VOID) ! 510: { ! 511: UCHAR ucLocalName[sizeof(LOCAL_DEVICE_NAME)+1] = LOCAL_DEVICE_NAME; ! 512: NETRESOURCE ToConnect; ! 513: UCHAR ucPassword[] = ""; ! 514: #define SZ_BUF 1000 ! 515: UCHAR ucRemoteName[SZ_BUF]; ! 516: UCHAR ucUserName [SZ_BUF] = "AUserName"; ! 517: DWORD dwSzBuf = SZ_BUF; ! 518: ! 519: ToConnect.lpRemoteName = ! 520: ConnectablesList[WHICH_TO_USE_FROM_LIST].lpRemoteName; ! 521: ToConnect.lpLocalName = ucLocalName; ! 522: ToConnect.lpProvider = NULL; ! 523: ToConnect.dwType = RESOURCETYPE_DISK; ! 524: ! 525: if (NO_ERROR != WNetAddConnection2(&ToConnect,(LPTSTR)ucPassword, ! 526: (LPTSTR)ucUserName,CONNECT_UPDATE_PROFILE)) ! 527: { PrintAppStyleAPIError(WNetAddConnection2,"AddGetGetCancel2"); ! 528: return; ! 529: } ! 530: ! 531: dwSzBuf = SZ_BUF; ! 532: ! 533: if (NO_ERROR != WNetGetConnection((LPTSTR)ucLocalName, ! 534: (LPTSTR)ucRemoteName,(LPDWORD)&dwSzBuf)) ! 535: { PrintAppStyleAPIError(WNetGetConnection,"AddGetGetCancel2"); ! 536: return; ! 537: } ! 538: ! 539: dwSzBuf = SZ_BUF; ! 540: ! 541: if (NO_ERROR != WNetGetUser((LPTSTR)ucLocalName, ! 542: (LPTSTR)ucUserName,(LPDWORD)&dwSzBuf)) ! 543: { PrintAppStyleAPIError(WNetGetUser,"AddGetGetCancel2"); ! 544: return; ! 545: } ! 546: ! 547: printf("\nDisk resource AddGetGetCancel2 connected = [%s], User name logged on to that resource = [%s]\n", ! 548: ucRemoteName,ucUserName); ! 549: ! 550: if (NO_ERROR != WNetCancelConnection2((LPTSTR)ucLocalName, ! 551: CONNECT_UPDATE_PROFILE,FALSE)) ! 552: { PrintAppStyleAPIError(WNetCancelConnection2,"AddGetGetCancel2"); ! 553: return; ! 554: } ! 555: } ! 556: ! 557: /****************************************************************************\ ! 558: * ! 559: * FUNCTION: PrintAPIError ! 560: * ! 561: \****************************************************************************/ ! 562: ! 563: VOID PrintAPIError(LPTSTR ApiTxt, ! 564: LPTSTR MsgTxt, ! 565: UINT Line, ! 566: LPTSTR File) ! 567: { DWORD dwLastError; ! 568: ! 569: dwLastError = GetLastError(); ! 570: switch (dwLastError) ! 571: { case NO_ERROR : ! 572: printf("\nNO_ERROR not expected (%s) line %d file %s",MsgTxt,Line,File); ! 573: break; ! 574: case ERROR_EXTENDED_ERROR : ! 575: { LPDWORD lpdwErrorCode; ! 576: ! 577: #define SZ_ERROR_BUF 4000 ! 578: UCHAR ucErrorBuf[SZ_ERROR_BUF]; ! 579: #define SZ_PROVIDER_NAME_BUF 400 ! 580: UCHAR ucProviderNameBuf[SZ_PROVIDER_NAME_BUF]; ! 581: ! 582: if (NO_ERROR != WNetGetLastError(lpdwErrorCode, ! 583: (LPTSTR)ucErrorBuf, ! 584: (DWORD)SZ_ERROR_BUF, ! 585: (LPTSTR)ucProviderNameBuf, ! 586: (DWORD)SZ_PROVIDER_NAME_BUF)) ! 587: { PERR("WNetGetLastError"); ! 588: } ! 589: else ! 590: { ! 591: #define szMsgBuf SZ_ERROR_BUF * 2 ! 592: UCHAR ucMsgBuf[szMsgBuf]; ! 593: ! 594: sprintf(ucMsgBuf, ! 595: "WNetGetLastError code = %d, Msg=[%s], Provider =[%s] line %d file %s", ! 596: lpdwErrorCode,ucErrorBuf,ucProviderNameBuf,Line,File); ! 597: PERR(ucMsgBuf); ! 598: } ! 599: } ! 600: break; ! 601: case ERROR_NOT_SUPPORTED : ! 602: printf("\nERROR_NOT_SUPPORTED (%s) line %d file %s",MsgTxt,Line,File); ! 603: break; ! 604: case ERROR_UNEXP_NET_ERR : ! 605: printf("\nERROR_UNEXP_NET_ERR (%s) line %d file %s",MsgTxt,Line,File); ! 606: break; ! 607: case ERROR_MORE_DATA : ! 608: printf("\nERROR_MORE_DATA (%s) line %d file %s",MsgTxt,Line,File); ! 609: break; ! 610: case ERROR_INVALID_ADDRESS : ! 611: printf("\nERROR_INVALID_ADDRESS (%s) line %d file %s",MsgTxt,Line,File); ! 612: break; ! 613: case ERROR_INVALID_PARAMETER : ! 614: printf("\nERROR_INVALID_PARAMETER (%s) line %d file %s",MsgTxt,Line,File); ! 615: break; ! 616: case ERROR_INVALID_PASSWORD : ! 617: printf("\nERROR_INVALID_PASSWORD (%s) line %d file %s",MsgTxt,Line,File); ! 618: break; ! 619: case ERROR_ACCESS_DENIED : ! 620: printf("\nERROR_ACCESS_DENIED (%s) line %d file %s",MsgTxt,Line,File); ! 621: break; ! 622: case ERROR_BUSY : ! 623: printf("\nERROR_BUSY (%s) line %d file %s",MsgTxt,Line,File); ! 624: break; ! 625: case ERROR_BAD_USERNAME : ! 626: printf("\nERROR_BAD_USERNAME (%s) line %d file %s",MsgTxt,Line,File); ! 627: break; ! 628: case ERROR_NOT_ENOUGH_MEMORY : ! 629: printf("\nERROR_NOT_ENOUGH_MEMORY (%s) line %d file %s",MsgTxt,Line,File); ! 630: break; ! 631: case ERROR_NO_NETWORK : ! 632: printf("\nERROR_NO_NETWORK (%s) line %d file %s",MsgTxt,Line,File); ! 633: break; ! 634: case ERROR_NOT_CONNECTED : ! 635: printf("\nERROR_NOT_CONNECTED (%s) line %d file %s",MsgTxt,Line,File); ! 636: break; ! 637: case ERROR_OPEN_FILES : ! 638: printf("\nERROR_OPEN_FILES (%s) line %d file %s",MsgTxt,Line,File); ! 639: break; ! 640: case ERROR_DEVICE_IN_USE : ! 641: printf("\nERROR_DEVICE_IN_USE (%s) line %d file %s",MsgTxt,Line,File); ! 642: break; ! 643: case ERROR_BAD_NET_NAME : ! 644: printf("\nERROR_BAD_NET_NAME (%s) line %d file %s",MsgTxt,Line,File); ! 645: break; ! 646: case ERROR_BAD_DEVICE : ! 647: printf("\nERROR_BAD_DEVICE (%s) line %d file %s",MsgTxt,Line,File); ! 648: break; ! 649: case ERROR_ALREADY_ASSIGNED : ! 650: printf("\nERROR_ALREADY_ASSIGNED (%s) line %d file %s",MsgTxt,Line,File); ! 651: break; ! 652: case ERROR_GEN_FAILURE : ! 653: printf("\nERROR_GEN_FAILURE (%s) line %d file %s",MsgTxt,Line,File); ! 654: break; ! 655: case ERROR_CONNECTION_UNAVAIL : ! 656: printf("\nERROR_CONNECTION_UNAVAIL (%s) line %d file %s",MsgTxt,Line,File); ! 657: break; ! 658: case ERROR_NO_NET_OR_BAD_PATH : ! 659: printf("\nERROR_NO_NET_OR_BAD_PATH (%s) line %d file %s",MsgTxt,Line,File); ! 660: break; ! 661: case ERROR_BAD_PROVIDER : ! 662: printf("\nERROR_BAD_PROVIDER (%s) line %d file %s",MsgTxt,Line,File); ! 663: break; ! 664: case ERROR_CANNOT_OPEN_PROFILE : ! 665: printf("\nERROR_CANNOT_OPEN_PROFILE (%s) line %d file %s",MsgTxt,Line,File); ! 666: break; ! 667: case ERROR_BAD_PROFILE : ! 668: printf("\nERROR_BAD_PROFILE (%s) line %d file %s",MsgTxt,Line,File); ! 669: break; ! 670: case ERROR_INVALID_HANDLE : ! 671: printf("\nERROR_INVALID_HANDLE (%s) line %d file %s",MsgTxt,Line,File); ! 672: break; ! 673: case ERROR_NO_MORE_ITEMS : ! 674: printf("\nERROR_NO_MORE_ITEMS (%s) line %d file %s",MsgTxt,Line,File); ! 675: break; ! 676: case ERROR_NOT_CONTAINER : ! 677: printf("\nERROR_NOT_CONTAINER (%s) line %d file %s",MsgTxt,Line,File); ! 678: break; ! 679: default : ! 680: printf("\n%s - unexpected return code=%d (%s) line %d file %s",ApiTxt,dwLastError,MsgTxt,Line,File); ! 681: break; ! 682: } ! 683: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.