| ||
In this section, I cover the aspects of getting access to LAN resources. There are two problems in this context: finding LAN resources and establishing connections to them. First, it is necessary to consider the main function intended for working with a network resource. The list provided here is not complete. However, the functions listed here are enough to enable your program to search for network resources and connect to them. I assume that you know how to work in a LAN and have basic knowledge about network devices, workstations, and so on.
First, consider the structure used in all network functions.
NETRESOURCE STRUC DwScope DWORD ? DwType DWORD ? DwDisplayType DWORD ? DwUsage DWORD ? LpLocalName DWORD ? LpRemoteName DWORD ? LpComment DWORD ? LpProvider DWORD ? NETRESOURCE ENDS
Here, the individual elements of the structure are described:
DwScope Takes one of the following values:
RESOURCE_CONNECTED This resource is connected.
RESOURCE_REMEMBERED This resource is memorized by the system to automatically establish a connection to it at startup.
RESOURCE_GLOBALNET This is a global network resource. You'll probably require only the last value.
DwType The resource type. The following values are possible:
RESOURCETYPE_ANY Any resource
RESOURCETYPE_DISK Disk drive
RESOURCETYPE_PRINT Network printer
DwDisplayType This field defines how this resource must be displayed by the network browser depending on its type. The list of types is numerous . For example, the RESOURCEDISPLAYTYPE_SERVER is defined for a network computer, the RESOURCEDISPLAYTYPE_GROUP is used for a group of computers, and so on.
dwUsage This is most frequently assumed to be zero.
lpLocalName This is the local name of the device: E :, LPT1 :, etc.
lpRemoteName This is the network name: \\super,\\NDI\EPSON , etc.
lpComment This string describes the network resource.
LpProvider This is the provider name. For the moment, assume that it can take one of the two possible values: Microsoft Network and NetWare. Other names are possible.
Now, consider the most popular network application program interface (API) functions:
WNetAddConnection2 Allows you to connect a network resource (disk or printer) to your computer.
First parameterThe address of the previously described NETRESOURCE structure. The following fields must be filled: dwType, lpLocalName, lpRemoteName , and lpProvider (usually, NULL ). An example of how to fill these fields will be provided later.
Second parameterThe password required for establishing a connection to the resource. In the case of a blank string, the connection doesn't require a password; if this parameter is set to NULL , then the password associated to the name is taken (this will be described later).
Third parameterThe username. If this parameter is set to NULL , then the default name will be used.
Fourth parameterThis parameter defines whether this connection is persistentin other words, whether the system will further connect to this resource automatically. If this parameter is set to zero, the connection is not persistent.
If the function completes successfully, it returns zero ( NO_ERROR ). The same is true for all functions described in the rest of this section.
WNetCancelConnection2 Disconnects the resource.
First parameterContains the pointer to the string that contains the resource name. If this is a local name, then the local resource will be disconnected. If the name of a remote resource is specified, all connections to that resource are terminated .
Second parameterDefines whether the system will later connect to this resource automatically. If this value is 0, then the system will reconnect to this resource at the next system startup.
Third parameterIf this parameter has a nonzero value, the resource will be disconnected even if there are opened files on the network disk or if the network printer is printing a job sent from your computer.
WnetOpenEnum Starts the search for network resources. Generally, network resources are organized into a tree-like structure. Therefore, searching for network resources is much alike searching for files using the directory tree.
First parameterThe dwScope field of the NETRESOURCE structure. Usually, it is assumed to be RESOURCE_GLOBALNET .
Second parameterThe dwType field of the NETRESOURCE structure. To search for various types of resources, set this value to RESOURCETYPE_ANY .
Third parameterThe dwUsage field of the NETRESOURCE structure. Usually, it is set to zero.
Fourth parameterThe address of the NETRESOURCE structure. If the address is zero ( NULL ), then the search will start from the lowest level (root); otherwise , the search will start from the level defined by the lpRemoteName and lpProvider fields.
Fifth parameterThe pointer to the variable that must receive the descriptor for further search.
WnetcloseEnum Closes the search. The only parameter of this function is the descriptor received when executing the WnetOpenEnum function.
WnetEnumResource Directly searches for network resources.
First parameterSearch descriptor.
Second parameterThe pointer to the variable that must contain the maximum number of resources that can be found per search operation. Usually, this variable is assumed to be 0FFFFFFFFH , which allows you to find all possible resources. If this function completes successfully, the variable will contain the number of found resources.
Third parameterThe pointer to the array, each element of which represents a NETRESOURCE structure. Obviously, this array must be large enough to hold as much information about the resource as required. Because the structure size is 32 bytes, in a large network the array size must be no less than 32,000 bytes.
Fourth parameterThe address of the variable that contains the array size. If the array size is too small, the variable will contain the required size.
I'll mention again that this function searches only resources of the current hierarchical level and doesn't search for all resources. Therefore, it is impossible to do without recursion.
WNetGetConnection Allows you to get information about the current connection.
First parameterAddress of the local name ( A :, C :, LPT2 , etc.)
Second parameterAddress of the buffer, into which the remote name will be loaded
Third parameterPointer to the variable that contains the buffer size
To complete this brief overview of the network API function, I'd like to mention again that I have described only the most important network functions. Furthermore, operating systems of the Windows NT family have some specific functions for working with network resources that are missing in Windows 9 x . By the way, be ready to discover that the behavior of the network API functions will be somewhat different in Windows 9 x , Windows NT, and Windows 2000. These differences will be emphasized when appropriate.
The program provided in Listing 17.2 demonstrates how to connect network drives . The command-line syntax of this program is as follows : NET \\SERVER\CC Z :. The first parameter is the name of the device being connected, including the name of the network server. The second parameter specifies the drive letter, to which the network disk is to be mapped.
; The NET program that connects to the network resource ; Usage: NET \SUPER\D Z: .586P ; Flat memory model .MODEL FLAT, stdcall ; Constants STD__OUTPUT_HANDLE equ -11 RESOURCETYPE_DISK equ 1h ; Prototypes of external procedures IFDEF MASM EXTERN lstrcatA@8:NEAR EXTERN lstrlen@4:NEAR EXTERN GetStdHandle@4:NEAR EXTERN WriteConsoleA@20:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetCommandLineA@0:NEAR EXTERN WNetAddConnection2A@16:NEAR ELSE LOCALS EXTERN lstrcatA:NEAR EXTERN lstrlen:NEAR EXTERN GetStdHandle:NEAR EXTERN WriteConsoleA:NEAR EXTERN ExitProcess:NEAR EXTERN GetCommandLineA:NEAR EXTERN WNetAddConnection2A:NEAR lstrcatA@8 = lstrcatA lstrlen@4 = lstrlen GetStdHandle@4 = GetStdHandle WriteConsoleA@20 = WriteConsoleA ExitProcess@4 = ExitProcess GetCommandLineA@0 = GetCommandLineA WNetAddConnection2A@16 = WNetAddConnection2A ENDIF ; Structures NETRESOURCE STRUC dwScope DWORD ? dwType DWORD ? dwDisplayType DWORD ? dwUsage DWORD ? lpLocalName DWORD ? lpRemoteName DWORD ? lpComment DWORD ? lpProvider DWORD ? NETRESOURCE ENDS ; INCLUDELIB directives for the linker IFDEF MASM includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\mpr.lib ELSE includelib c:\tasm32\lib\import32.lib ENDIF ;--------------------------------------------- ; Data segment _DATA SEGMENT BUF1 DB 100 dup(0) BUF2 DB 100 dup(0) LENS DWORD ? ; Number of displayed characters HANDL DWORD ? NR NETRESOURCE <0> PUSTO DB 0 ERR2 DB "Error!", 0 ERR1 DB "Few parameters!", 0 ST1 DB "->", 0 _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the input and output handle PUSH STD_OUTPUT_HANDLE CALL GetStdHandle@4 MOV HANDL, EAX ; Get the number of parameters CALL NUMPAR CMP EAX, 3 JNB PAR_OK LEA EBX, ERR1 CALL SETMSG JMP _END PAR_OK: ; Get the parameters MOV EDI, 2 LEA EBX, BUF1 CALL GETPAR MOV EDI, 3 LEA EBX, BUF2 CALL GETPAR ; Attempt to establish a connection ; First, fill the NETRESOURCE structure ; For Windows NT, NR.dwType = 0 MOV NR.dwType, RESOURCETYPE_DISK LEA EAX, BUF2 MOV NR.lpLocalName, EAX LEA EAX, BUF1 MOV NR.lpRemoteName, EAX MOV NR.lpProvider, 0 ; Call the function that establishes the connection PUSH 0 PUSH OFFSET PUSTO PUSH OFFSET PUSTO PUSH OFFSET NR CALL WNetAddConnection2A@16 CMP EAX, 0 JE _OK ; Error message LEA EBX, ERR2 CALL SETMSG JMP _END _OK: ; Information message about successful connection PUSH OFFSET ST1 PUSH OFFSET BUF1 CALL lstrcatA@8 PUSH OFFSET BUF2 PUSH OFFSET BUF1 CALL lstrcatA@8 LEA EBX, BUF1 CALL SETMSG _END: PUSH 0 CALL ExitProcess@4 ; Determine the number of parameters (->EAX) NUMPAR PROC CALL GetCommandLineA@0 MOV ESI, EAX ; Pointer to the string XOR ECX, ECX ; Counter MOV EDX, 1 ; Flag @@L1: CMP BYTE PTR [ESI], 0 JE @@L4 CMP BYTE PTR [ESI], 32 JE @@L3 ADD ECX, EDX ; Parameter number MOV EDX, 0 JMP @@L2 @@L3: OR EDX, 1 @@L2: INC ESI JMP @@L1 @@L4: MOV EAX, ECX RET NUMPAR ENDP ; Get the parameter ; EBX - Points to the buffer, in which the parameter will be loaded ; Null-terminated string is loaded into the buffer ; EDI - Parameter number GETPAR PROC CALL GetCommandLineA@0 MOV ESI, EAX ; Pointer to the string XOR ECX, ECX ; Counter MOV EDX, 1 ; Flag @@L1: CMP BYTE PTR [ESI], 0 JE @@L4 CMP BYTE PTR [ESI], 32 JE @@L3 ADD ECX, EDX ; Parameter number MOV EDX, 0 JMP @@L2 @@L3: OR EDX, 1 0@L2: CMP ECX, EDI JNE @@L5 MOV AL, BYTE PTR [ESI] CMP AL, 32 JE @@L5 MOV BYTE PTR [EBX], AL INC EBX @@L5: INC ESI JMP @@L1 @@L4: MOV BYTE PTR [EBX], 0 RET GETPAR ENDP ; Message output ; EBX -> string SETMSG PROC PUSH EBX CALL lstrlen@4 PUSH 0 PUSH OFFSET LENS PUSH EAX PUSH EBX PUSH HANDL CALL WriteConsoleA@20 RET SETMSG ENDP _TEXT ENDS END START
To translate the program presented in Listing 17.2, issue the following commands for MASM32:
ml /c /coff /DMASM net.asm link /subsystem:console net.obj
Issue the following commands for TASM32:
tasm32 /ml net.asm tlink32 -ap net.obj
When considering the program presented in Listing 17.2, pay attention to the following:
Note how local labels are used. MASM recognizes local labels automatically. TASM, on the other hand, requires the local labels to be preceded by the @@ prefix. Additionally, the LOCALS directive must be inserted in the beginning of the program.
Note one important feature of the WNetAddConnection2A@16 function. For Windows NT and later operating systems of this family, the dwType field of the NETRESOURCE structure must contain zero instead of RESOURCETYPE_DISK . Unfortunately, there are many other similar differences when working with LAN resources. If you plan to undertake a serious programming task related to working with LAN resources, you'll have to test your program on different computers in various networks.
Naturally, this program is far from perfect. Therefore, try to improve it. In particular, it would be useful to check whether the local device is network device and, if this is the case, ask permission to establish a persistent connection. In this case, it is necessary to first disconnect the device using the WNetCancelConnection2 function.
When it is necessary to connect a network printer, the dwType field must be set to RESOURCETYPE_PRINT .
The program in Listing 17.3 carries out a recursive search for network resources. It operates in the console mode and displays on the screen provider's name and remote name of the resources found. This program must correctly operate in both Microsoft and Novell networks.
; The NET1 program that searches for ; network resources .586P ; Flat memory model .MODEL FLAT, stdcall ; Constants STD_OUTPUT_HANDLE equ -11 RESOURCETYPE_DISK equ 1h RESOURCE_GLOBALNET equ 2h RESOURCETYPE_ANY equ 0h ; Prototypes of external procedures IFDEF MASM EXTERN CharToOemA@8:NEAR EXTERN RtlMoveMemory@12:NEAR EXTERN WNetCloseEnum@4:NEAR EXTERN WNetEnumResourceA@16:NEAR EXTERN WNetOpenEnumA@20:NEAR EXTERN lstrcpyA@8:NEAR EXTERN lstrcatA@8:NEAR EXTERN lstrlen@4:NEAR EXTERN GetStdHandle@4:NEAR EXTERN WriteConsoleA@20:NEAR EXTERN ExitProcess@4:NEAR EXTERN GetCommandLineA@0:NEAR ELSE EXTERN CharToOemA:NEAR EXTERN RtlMoveMemory:NEAR EXTERN WNetCloseEnum:NEAR EXTERN WNetEnumResourceA:NEAR EXTERN WNetOpenEnumA:NEAR EXTERN lstrcpyA:NEAR EXTERN lstrcatA:NEAR EXTERN lstrlen:NEAR EXTERN GetStdHandle:NEAR EXTERN WriteConsoleA:NEAR EXTERN ExitProcess:NEAR EXTERN GetCommandLineA: NEAR CharToOemA@8 = CharToOemA RtlMoveMemory@12 = RtlMoveMemory WNetCloseEnum@4 = WNetCloseEnum WNetEnumResourceA@16 = WNetEnumResourceA lstrcpyA@8 = lstrcpyA WNetOpenEnumA@20 = WNetOpenEnumA lstrcatA@8 = lstrcatA lstrlen@4 = lstrlen GetStdHandle@4 = GetStdHandle WriteConsoleA@20 = WriteConsoleA ExitProcess@4 = ExitProcess GetCommandLineA@0 = GetCommandLineA ENDIF ; Structures NETRESOURCE STRUC dwScope DWORD ? dwType DWORD ? dwDisplayType DWORD ? dwUsage DWORD ? lpLocalName DWORD ? lpRemoteName DWORD ? lpComment DWORD ? lpProvider DWORD ? NETRESOURCE ENDS ; INCLUDELIB directives for the linker IFDEF MASM includelib c:\masm32\lib\user32.lib includelib c:\masm32\lib\kernel32.lib includelib c:\masm32\lib\mpr.lib ELSE includelib c:\tasm32\lib\import32.lib ENDIF ;--------------------------------------------- ; Data segment _DATA SEGMENT LENS DWORD ? ; Number of displayed characters HANDL DWORD ? NR NETRESOURCE <0> ENT DB 13, 10, 0 BUF DB 100 dup(0) _DATA ENDS ; Code segment _TEXT SEGMENT START: ; Get the input and output handle PUSH STD_OUTPUT_HANDLE CALL GetStdHandle@4 MOV HANDL, EAX ; Start the network search procedure PUSH 0 PUSH OFFSET NR CALL SEARCH _END: PUSH 0 CALL ExitProcess@4 ; Search procedure PAR1 EQU [EBP+8] ; Pointer to the structure PAR2 EQU [EBP+0CH] ; Flag ; Local variables HANDLP EQU [EBP-4] ; Search handle CC EQU [EBP-8] NB EQU [EBP-12] NR1 EQU [EBP-44] ; Structure BUFER EQU [EBP-144] ; Buffer RS EQU [EBP-32144] ; Array of structures SEARCH PROC PUSH EBP MOV EBP, ESP SUB ESP, 32144 CMP DWORD PTR PAR2, 0 JNE SECOND ; NULL at first startup XOR EBX, EBX JMP FIRST SECOND: ; Startup in the course of recursive search ; First, copy the structure into a local ; variable (this is not required for this program) PUSH 32 PUSH DWORD PTR PAR1 LEA EAX, DWORD PTR NR1 PUSH EAX CALL RtlMoveMemory@12 ; In case a recursive search points to a structure LEA EBX, DWORD PTR NR1 FIRST: ; Startup at the first call LEA EAX, HANDLP PUSH EAX PUSH EBX PUSH 0 PUSH RESOURCETYPE_ANY PUSH RESOURCE_GLOBALNET CALL WNetOpenEnumA@20 CMP EAX, 0 JNE _EN ; Main search REPI: ; Starting the WNetEnumResource function ; Size of the array of NETRESOURCE structures MOV DWORD PTR NB, 32000 LEA EAX, NB PUSH EAX LEA EAX, RS PUSH EAX ; Get the maximum number of objects MOV DWORD PTR CC, OFFFFFFFFH LEA EAX, CC PUSH EAX PUSH DWORD PTR HANDLP CALL WNetEnumResourceA@16 CMP EAX, 0 JNE _CLOSE ; Loop by the resulting array MOV ESI, CC SHL ESI, 5 ; Multiply by 32 MOV EDI, 0 LOO: CMP EDI, ESI JE REPI ; Information output ; Provider MOV EBX, DWORD PTR RS[EDI]+28 CALL SETMSG ; Remote name MOV EBX, DWORD PTR RS[EDI]+20 CALL SETMSG ; Save the required registers PUSH ESI PUSH EDI ; Recursive call PUSH 1 LEA EAX, DWORD PTR RS[EDI] PUSH EAX CALL SEARCH ; Restore registers POP EDI POP ESI ADD EDI, 32 JMP LOO ;---------------------------------- JMP REPI ;---------------------------------- _CLOSE: PUSH DWORD PTR HANDLP CALL WNetCloseEnum@4 _EN: MOV ESP, EBP POP EBP RET 8 SEARCH ENDP ; Display the message ; EBX -> string SETMSG PROC ; Copy the text into a separate buffer PUSH EBX PUSH OFFSET BUF CALL lstrcpyA@8 LEA EBX, BUF ; Convert for console output PUSH EBX PUSH EBX CALL CharToOemA@8 ; Add the line feed PUSH OFFSET ENT PUSH EBX CALL lstrcatA@8 ; Determine the string length PUSH EBX CALL lstrlen@4 ; Display the string PUSH 0 PUSH OFFSET LENS PUSH EAX PUSH EBX PUSH HANDL CALL WriteConsoleA@20 RET SETMSG ENDP _TEXT ENDS END START
To translate the program presented in Listing 17.3, issue the following commands using MASM32:
ml /c /coff /DMASM net1.asm link /subsystem:console /STACK:1000000,1000000 net1.obj
Issue the following commands using TASM32:
tasm32 /ml net1.asm tlink32 -ap -S:1000000 -Sc:1000000 net1.obj
The program in Listing 17.3 is complicated and requires detailed comments. First, I would like to point out that if you want a proper understanding of network programming (in this context, network programming is interpreted as programming for LANs), [i] it is absolutely necessary to write several programs on your own. The programs presented here will serve as the starting point.
You encountered local variables when considering file search of the directory tree. This problem is similar; however, it has certain differences. In this case, too many local variables are used. Because of this, I explicitly declared a large volume for the stack (the STACK command-line option for MASM and the s and sc commandline options for TASM32). By default, the linker sets only 8 KB, which, obviously, is not sufficient.
The WnetEnumResource function requires the array of NETRESOURCE structures as ne of its parameters. The size of a single structure is 32 bytes. I reserved 1,000 such structures. Isn't this too much, you might ask? To tell the truth, I never encountered a LAN with 1,006 workstations. However, I have seen a LAN, in which one of the servers contained about 800 network directories. Honestly, the style of programming that I demonstrate here is not the best possible. A more correct approach would be to first call the WnetEnumResource function, then specify a buffer smaller than 32 bytes, in which case the required size will be returned in the variable containing the buffer size. Then, knowing the required size, the program must request the required buffer from the operating system and repeat the call to WnetEnumResource . Although this approach is more correct, it is more difficult to implement.
In a recursive call to the SEARCH procedure, the first parameter is the pointer to the element of the array composed of the NETRESOURCE structures. I copied the element of this array into the local variable NR1 . Principally, in this program, such action is not required, and you could immediately use the obtained pointer. However, in more a complicated program, you'll have to do this.
Note that in the course of information output I copied the string into the buffer that then is used for output. This isn't a fancy code; this is a necessity. Before output, I added the codes 13 and 10 to the string end. Because I output the strings that will be used for further searches, I must use an additional buffer for output.
[i] Nowadays, the term network programming is often interpreted as Internet programming or using Internet approaches and methods in a LAN (intranet). However, this chapter describes a relatively narrow range of tasks those that relate only to LANs.
| ||