0

Recently I started learning WIN API from Microsoft documentation and I decided to look at every detail with my IDE features. LoadIconA is a function that takes HINSTANCE and LPCSTR as parameters. we pass IDI_APPLICATION as the second parameter. This is a macro That expands as

#define IDI_APPLICATION MAKEINTRESOURCE(32512) // winuser.h

Moreover, MAKEINTRESOURCE expands as ANSI or UNICODE equivalent. I am looking at ANSI equivalent.

#define MAKEINTRESOURCEA(i) ((LPSTR)((ULONG_PTR)((WORD)(i)))) // winuser.h

This where I noticed that integer I (here 32512) is ultimately typecasted into LPSTR which is passed into the LoadIconA function. But when I do the same as

#include <windows.h>
#include <iostream>
int main(){
     LPCSTR hello = MAKEINTRESOURCEA(32512);
     std::cout << hello << std::endl;
}

My program crashes. Does someone have any idea what's going over here?

Also, I didn't notice any library dependencies. sorry for the Ques Title, I didn't find any Proper title.

  • 1
    _"...Converts an integer value to a resource type compatible with the resource-management functions. ..."_ https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-makeintresourcea _"...The return value should be passed only to functions __which explicitly indicate that they accept MAKEINTRESOURCE as a parameter__. .."_ – Richard Critten Nov 10 '20 at 16:08
  • `1 != 32512` isnt that a difference? You are not "doing the same" – 463035818_is_not_an_ai Nov 10 '20 at 16:09
  • @idclev463035818 - it's for accessing strings in a Windows Resource file and built-in string resources using the WinAPI only. – Richard Critten Nov 10 '20 at 16:10
  • I think `hello` should be of `LPSTR` type instead of `LPCSTR` – Harry Nov 10 '20 at 16:10
  • @idclev463035818 It doesnt work either. –  Nov 10 '20 at 16:10
  • @RichardCritten which explicitly indicate that they accept MAKEINTRESOURCE as a parameter. How does This Happen. –  Nov 10 '20 at 16:11
  • 1
    i didnt claim that it will work when you do the same, but I don't understand why you expect to get the same result when you do something different – 463035818_is_not_an_ai Nov 10 '20 at 16:12
  • 1
    @vectorX `LoadIconA` _"...The name of the icon resource to be loaded. Alternatively, this parameter can contain the resource identifier in the low-order word and zero in the high-order word. __Use the MAKEINTRESOURCE macro__ to create this value...."_ https://learn.microsoft.com/en-us/windows/win32/api/winuser/nf-winuser-loadicona – Richard Critten Nov 10 '20 at 16:13
  • 1
    Sounds to me like inside `LoadIconA` it determines whether the LPCSTR argument is in the range created by MAKEINTRESOURCE, and if so it never tries to use the value directly as a string, but instead uses it as an index into some other container of strings. When you `cout << hello` though, you're not doing that - you're assuming it's a pointer to a text, and following an invalid pointer. Hence, crash. – Tony Delroy Nov 10 '20 at 16:16
  • @TonyDelroy Exactly - it's a kludge dating back to 16 bit Windows where every byte was precious. – Richard Critten Nov 10 '20 at 16:17
  • 1
    Very very very old Windows "trick". It's *either* a resource id *or* a pointer to a string. In Windows, the first 64K of address space is always invalid. So you know it's a resource id if the pointer value is < 0x10000, so it's expected to crash with this code. https://devblogs.microsoft.com/oldnewthing/20110217-00/?p=11463 – Simon Mourier Nov 10 '20 at 16:53

1 Answers1

3

This macro casts an integer to a pointer. Obviously (unless you happen to guess an integer representing a valid pointer) the result is an invalid pointer, in the sense that dereferencing it causes undefined behavior (normally a crash).

<< tries to dereference this invalid pointer (to print it as an array of characters) and crashes.

WinAPI functions that can work with MAKEINTRESOURCE have to check if pointers they receive have one of those special values, and only dereference them if it's not the case.

HolyBlackCat
  • 78,603
  • 9
  • 131
  • 207
  • Actually there are Thousands of such consecutive conversion. so, This can't be special. –  Nov 10 '20 at 16:20
  • @vectorX Then the WinAPI functions probably check for a range of values. – HolyBlackCat Nov 10 '20 at 16:27
  • 1
    All such 'special' values are less than 65536 (2^16) and thus it's easy to judge whether to perform additional lookup or just attempt to use the value as a pointer. – SoronelHaetir Nov 10 '20 at 16:28
  • @vectorX: All those functions aren't special; they just forward to `FindResourceA/W` which _is_ special. – MSalters Nov 10 '20 at 16:33