Passing structure pointer as parameter to a function

New to FreeBASIC? Post your questions here.
Post Reply
Wormgrinder
Posts: 2
Joined: Dec 25, 2023 20:04

Passing structure pointer as parameter to a function

Post by Wormgrinder »

I'm trying to use function InternetCrackUrl from WinAPI. The last parameter requires a pointer to the URL_COMPONENTS structure, but I don’t even know how to properly declare the structure and pass the pointer to the function, and then get some value from this structure. I tried it like this and failed (The function itself returns true, but I can't get the value from the structure):

Code: Select all

#define UNICODE
#include once "windows.bi"
#include once "win\wininet.bi"

Dim sTestUrl As String = "https://www.freebasic.net/"
Dim pwszBuffer As WString Ptr = Allocate((Len(sTestUrl) + 1) * SizeOf(WString))
*pwszBuffer = sTestUrl
Dim lpszTestUrl As LPCWSTR = pwszBuffer

Print(*lpszTestUrl)

Dim lpUrlComponents As LPURL_COMPONENTS = New URL_COMPONENTS
InternetCrackUrl(lpszTestUrl, Len(*lpszTestUrl), 0, lpUrlComponents)

Print(*lpUrlComponents.lpszHostName) 'Error: Symbol not a CLASS, ENUM, TYPE or UNION type, before '.'

Deallocate(pwszBuffer)
Delete lpUrlComponents

Sleep
coderJeff
Site Admin
Posts: 4332
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Passing structure pointer as parameter to a function

Post by coderJeff »

Hi Wormgrinder, welcome.

You have most of what is needed in your program to use the function. But if you read the MS documentation a little closer and you should see the details needed to call the function:
- dwStructSize must be set to size of structure
- if buffer and size are both zero, nothing return
- if buffer = NULL and size is non-zero ... see the docs -- this method didn't work for me
- if buffer is allocated and size non-zero, some information is copied -- this did work for me

URL_COMPONENTS is already declared in win headers, so you don't need to declare this.
Yeah, the error message is misleading...

See operator precedence with respect to *lpUrlComponents.lpszHostName

The member access '.' operator takes precedence over the the value of '*' operator

lpUrlComponents is a pointer and also lpUrlComponents->lpszHostName is a pointer,
So should instead be:
*lpUrlComponents->lpszHostName
or
*(*lpUrlComponents).lpszHostName

Code: Select all

#define UNICODE
#include once "windows.bi"
#include once "win\wininet.bi"

#define allocLPWSTR( n ) cast( LPWSTR, callocate((n + 1) * SizeOf(WString))) 
#define freeLPWSTR( s )  if s then: deallocate s: end if

Dim sTestUrl As String = "https://www.freebasic.net/"
Dim lpszTestUrl As WString Ptr = allocLPWSTR( len(sTestUrl) )
*lpszTestUrl = sTestUrl

Print *lpszTestUrl

Dim lpUrlComponents As LPURL_COMPONENTS = New URL_COMPONENTS

with *lpUrlComponents
	'' dwStructSize must be set to size of structure 
	.dwStructSize = sizeof( URL_COMPONENTS )

	'' items to be returned must be allocated a buffer and max length
	.lpszHostName = allocLPWSTR( 1000 )
	.dwHostNameLength = 1000
end with

InternetCrackUrl(lpszTestUrl, Len(*lpszTestUrl), ICU_DECODE, lpUrlComponents)

Print *lpUrlComponents->lpszHostName

freeLPWSTR(lpUrlComponents->lpszHostName)
freeLPWSTR(lpszTestUrl)
Delete lpUrlComponents

Sleep
Wormgrinder
Posts: 2
Joined: Dec 25, 2023 20:04

Re: Passing structure pointer as parameter to a function

Post by Wormgrinder »

coderJeff wrote: Dec 26, 2023 0:51 Hi Wormgrinder, welcome.
Hi, Jeff. Thank you so much for this lesson. It helps a LOT! I would be glad if you could tell me about the purpose of the cast function in the allocLPWSTR macro. We're converting the address of allocated memory to a wide string pointer?
coderJeff
Site Admin
Posts: 4332
Joined: Nov 04, 2005 14:23
Location: Ontario, Canada
Contact:

Re: Passing structure pointer as parameter to a function

Post by coderJeff »

Wormgrinder wrote: Dec 26, 2023 6:59 could tell me about the purpose of the cast function in the allocLPWSTR macro. We're converting the address of allocated memory to a wide string pointer?
Correct

callocate() returns a pointer to a type of ANY. (like a void* in C ... if you happen to know any C).
the cast( LPWSTR, ... ) converts the ANY PTR type to a LPWSTR type
Both are still pointers, but gives the compiler different information about the pointer, what it can do, where it can be used, and enables more type checking.

By telling the compiler to restrict the pointer's use to a specific type of pointer, the compiler may be able to detect problems and warn (or error) on mismatched pointer types.
Post Reply