Annotation of q_a/samples/winnet/winnet.c, revision 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.