Search code examples
cwindowswinapiunicodeansi

GetTempPathA how would I know size in advance?


I am coding in C, using the Windows API.

I was looking at the GetTempPathA() function here, and have included the function's syntax below.

DWORD GetTempPathA(
  DWORD nBufferLength,
  LPSTR lpBuffer
);

I can see the path will be stored in lpBuffer, but I could not understand how I am expected to know what size to set the DWORD nBufferLength to - I expect people with more Windows development experience will tell me it is one value for ANSI language systems and another for Unicode, but I would rather ask the professionals here on Stackoverflow for guidance?

I would assume it needs to be set to the longest value possible for a file path, as perhaps the user somehow changed the default location to a longer path elsewhere on the system, but I am only guessing.

This appears to be just an ANSI function, however during my time looking over the documentation on MSDN I often find functions which have an ANSI and Unicode function (which end in A and W respectively). I do understand the difference between them, but if I had to create a buffer what would the maximum input size be?

Lastly, when answering please keep in mind that I do enjoy writing backwards compatible applications, as many of my friends live in third world countries without access to the latest Windows operating systems.


Solution

  • You can either use a fixed-size buffer that will hold the maximum possible path length (e.g. char buffer[MAX_PATH+1];) or, if you want to allocate just enough buffer space, call the GetTempPathA function initially with a nBufferLength argument of zero and a NULL value for lpBuffer. (The latter is not fully documented, from what I can see, but the code below works and that system is used for many other WinAPI calls that require a buffer of a given size.)

    Test code:

    #include <Windows.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        DWORD answer = GetTempPathA(0, NULL);
        printf("%lu\n", answer);
        char* buffer = malloc(answer);
        answer = GetTempPathA(answer, buffer);
        printf("Temp path is: >>>%s<<< (length = %lu)\n", buffer, answer);
        free(buffer);
        return 0;
    }
    

    Note that the value of answer in the first call will be one greater than in the second call (because the former will include room for the nul terminator).

    From the documentation:

    Return Value

    If the function succeeds, the return value is the length, in TCHARs, of the string copied to lpBuffer, not including the terminating null character. If the return value is greater than nBufferLength, the return value is the length, in TCHARs, of the buffer required to hold the path.

    Or, for a version that works 'generically', for both Unicode and multi-byte (ANSI) builds, use the following:

    #include <Windows.h>
    #include <tchar.h>
    #include <stdio.h>
    #include <stdlib.h>
    
    int main()
    {
        DWORD answer = GetTempPath(0, NULL);
        _tprintf(TEXT("%lu\n"), answer);
        TCHAR* buffer = malloc(sizeof(TCHAR) * answer);
        answer = GetTempPath(answer, buffer);
        _tprintf(TEXT("Temp path is: >>>%s<<< (length = %lu)\n"), buffer, answer);
        free(buffer);
        return 0;
    }