Annotation of q_a/samples/winnet/winnet.c, revision 1.1.1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.