|
|
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.