0

I'm trying to make a directory using _mkdir() but it keeps giving me an "invalid parameter" error. It does work if I hard-code the path. I'm receiving the name of a desktop through a socket.

This is my code:

char getinfo[CMP_SIZE] = "getinfo";
for (unsigned int i = 0; i < master.fd_count; i++)
{
    char infoPath[1000];

    s = master.fd_array[i];

    if (s != ListenSocket)
    {
        int r = sendStrBuffer(s, getinfo, CMP_SIZE);
        if (r == SOCKET_ERROR)
        {
            printf("error\n");
        }
                            
        char *whoami = recvStrBuffer(s);
// output: desktop-00hlt29\name

        for (int i = 0; whoami[i] != '\0'; i++) {
            if (whoami[i] == '\\') {
                whoami[i] = '_';
            }
        }

        printf("whoami: %s\n", whoami); // output: desktop-00hlt29_name
        sprintf(infoPath, "C:\\Users\\name\\Desktop\\%s", whoami);
        //strcat_s(infoPath, whoami);
        printf("infoPath: %s\n", infoPath); //output: C:\\Users\\name\\Desktop\\desktop-00hlt29_name
                            
        if (_mkdir(infoPath) == -1)  // It works if I do like this: _mkdir("C:\\Users\\name\\Desktop\\desktop-00hlt29_name")
        {
            printf("Failed to create directory: %s\n", strerror(errno)); // output: Failed to create directory: Invalid argument
        }
        else 
        {
            printf("Directory created successfully\n");
        }
    }
}
  • 1
    OT: It's [`mkdir()`](https://pubs.opengroup.org/onlinepubs/9699919799.2018edition/functions/mkdir.html), not `_mkdir()`. Don't believe [Microsoft's "deprecated" bullhockey](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/mkdir?view=msvc-170). `mkdir()` **predates** the C standard, and [the **purpose** of the standardization of C](https://port70.net/~nsz/c/c89/rationale/a.html#1-1) is to "codif[y[ the common, existing definition of C and which promotes the portability of user programs across C language environments". If MS really cared, they'd support last century's C99. – Andrew Henle Feb 28 '23 at 19:13
  • 1
    Note that MSVC's version can only make the bottom level: the intermediate directories must exist. – Weather Vane Feb 28 '23 at 19:17
  • @AndrewHenle How can I use mkdir() without the error. – kyle walker Feb 28 '23 at 19:17
  • @WeatherVane Yes all directories exist except for the one that I want to create – kyle walker Feb 28 '23 at 19:18
  • It will also return an error if the requested directory already exists. – Weather Vane Feb 28 '23 at 19:19
  • @WeatherVane Yes I know. The file that I want to create doesn't exist. – kyle walker Feb 28 '23 at 19:21
  • I check all the variables if they are valid and they are. – kyle walker Feb 28 '23 at 19:26
  • 2
    @AndrewHenle MSVC will still compile those _functions without the underscore. The source file just needs `#define _CRT_NONSTDC_NO_DEPRECATE` to defeat the warning. – Weather Vane Feb 28 '23 at 19:28
  • @kylewalker Useful also post the exact input used and output seen. – chux - Reinstate Monica Feb 28 '23 at 19:28
  • @WeatherVane I get the same result using mkdir(). I honestly think it has to do with sprintf – kyle walker Feb 28 '23 at 19:30
  • The code shown outputs with `printf("infoPath: %s\n", infoPath);` Is it correct and on an exisiting path, with write permission? – Weather Vane Feb 28 '23 at 19:32
  • @WeatherVane Yes I do have write permission. If I just hardcode the path (the path where I want to create the folder) it works. – kyle walker Feb 28 '23 at 19:39
  • @AndrewHenle: `mkdir` is not part of the C standard. – Eric Postpischil Feb 28 '23 at 19:46
  • @AndrewHenle Microsoft is correct here. Since `mkdir()` isn't part of C nor C++, it should live in the compiler vendor's private namespace reserved for non-standard extensions, i.e. `_mkdir()`. Rationale is [here](https://stackoverflow.com/a/33358701/1889329). – IInspectable Feb 28 '23 at 19:48
  • Best to post the _true_ cut & paste output, not "C:\\Users\\name\\Desktop\\desktop-00hlt29_name". – chux - Reinstate Monica Feb 28 '23 at 19:48
  • 1
    Edit the question to provide a [mre]. There is no reason to have all that code for a `mkdir` or `_mkdir` problem. Use the debugger or modify the program to print the argument being passed to `_mkdir`. If the string passed to `_mkdir` is what you want, then reproduce the problem as a program with no code in `main` except a call to `_mkdir` with that string and a display of its return value. If the string is not want you want, then the problem is somewhere else in the program, and you reduce it to a [mre] that shows just how the string is computed. – Eric Postpischil Feb 28 '23 at 19:49
  • @chux-ReinstateMonica name stand for my name. I'm sure that's not the problem because if I hardcode it it works. – kyle walker Feb 28 '23 at 19:50
  • @kylewalker it not the _name_. Yet since you do not want to post input use, output seen, output expected nor a [mcve], we are not efficiently attacking this problem. Good luck. – chux - Reinstate Monica Feb 28 '23 at 19:52
  • 1
    You have confused the question (and invalidated answers) by removing the environment variable `%username%`. That works with the shell command `MKDIR` but not with the library function. Please don't ask "shifting sand" questions. – Weather Vane Feb 28 '23 at 19:53
  • @EricPostpischil *`mkdir` is not part of the C standard* As are none of the functions in the entire Win32 API: https://learn.microsoft.com/en-us/windows/win32/api/ Note that none of those start with an underscore. But Microsoft doesn't mark those as "deprecated". – Andrew Henle Mar 01 '23 at 11:07
  • @IInspectable *Microsoft is correct here.* **No, they are not**. If that were the Microsoft standard, they'd mark the entire Win32 API as "deprecated" too. None of those calls start with an underscore. That rationale fell out of the north end of a southbound bull. – Andrew Henle Mar 01 '23 at 11:10
  • @AndrewHenle The Win32 API is a library, that's not part of Standard C. As the library vendor you cannot move symbols it exposes into the namespace that's reserved for use by the language implementation (C in this case). Not sure what point you're trying to make here, but surely it would make your life a whole easier on you if you acknowledged that Microsoft does get things right, every now and again. – IInspectable Mar 01 '23 at 11:48
  • @IInspectable Microsoft is throwing FUD here with their inconsistent application of the C standard to call `mkdir()` "deprecated". `CreateFile()` is every bit in the namespace as `mkdir()` is, but Microsoft implies `mkdir()` is "deprecated" universally, whereas it's just Microsoft doing Microsoft things to portable code. Your defense is lame - it uses specifics of Microsoft's implementation to excuse not "deprecating" `CreateFile()`. Microsoft could have implemented `mkdir()` in the same manner. But they didn't. If Microsoft really cared about C standard compliance, they'd implement VLAs. – Andrew Henle Mar 01 '23 at 12:42
  • @AndrewHenle You seem to be confused about the text you read. `mkdir`, the **name**, is marked as deprecated. The equivalent implementation has been moved behind the name `_mkdir`, which is in line with the C Standard, but the original `mkdir` symbol is still there. You'll get a warning if you use it. Now that said, Microsoft doesn't care any more about the C Standard than what is inherited by the C++ Standard, which this namespacing happens to be a part of. I don't know what `CreateFile` has anything to do with this. It's part of an arbitrary library, not the language implementation. – IInspectable Mar 01 '23 at 13:23
  • @IInspectable Why do you have to put `CreateFile()` in some special category of "part of an arbitrary library"? `mkdir()` is **also** part of "an arbitrary library". `CreateFile()` is a function name that, on Windows, is in the C namespace exactly the same as `mkdir()` is. You have to force-fit `CreateFile()` (and the entire Win32 API...) into some special category to try to claim it's exempt from the same C standard that Microsoft FUDtastically applies to `mkdir()` to "deprecate" it. Microsoft still doesn't comply with last **century's** C standard even with this **century** almost 1/4 over. – Andrew Henle Mar 01 '23 at 13:46
  • *"Why do you have to put `CreateFile()` in some special category of 'part of an arbitrary library'?"* - Because that's what it is. It isn't part of of any language implementation nor language support library, and doesn't ship with Microsoft's C or C++ compiler. `mkdir`, on the other hand, does. Now just because Microsoft doesn't ship a fully conforming C99 compiler, does that mean they shouldn't stay in-spec for the parts they have implemented? As for `mkdir` or `_mkdir`, specifically, no one should be using it on Windows anyway. – IInspectable Mar 01 '23 at 16:48
  • @IInspectable You not only continue to make excuses for Microsoft, you're downright **wrong**: "Because that's what it is. It isn't part of of any language implementation nor language support library, and doesn't ship with Microsoft's C or C++ compiler. `mkdir`, on the other hand, does." `mkdir()` is part of the [Universal C Runtime Library](https://learn.microsoft.com/en-us/cpp/c-runtime-library/reference/crt-alphabetical-function-reference?view=msvc-170) (among other libraries IIRC), **which ships with all recent versions of Windows**. – Andrew Henle Mar 01 '23 at 18:56
  • @IInspectable [**Universal CRT deployment**](https://learn.microsoft.com/en-us/cpp/windows/universal-crt-deployment?view=msvc-170) "The Universal CRT (UCRT) is a **Microsoft Windows operating system component. It's included as part of the operating system in Windows 10 or later, and Windows Server 2016 or later**." Your excuse for Microsoft is utterly invalid. `mkdir()` is in the exact same set of libraries that ship with all versions of Windows that the entire Win32 API is. Yet Microsoft only "deprecates" portable functions and does not apply that same C-standard rationale to MS ones – Andrew Henle Mar 01 '23 at 18:58
  • @AndrewHenle `_mkdir` is in the UCRT, *now*. It hasn't always been like that, and the deprecation of the `mkdir` symbol dates back to before the UCRT was a thing. The UCRT shipping as part of the OS doesn't make a difference. It still has to follow language rules regardless (unlike, say, kernel32.dll). It is not an arbitrary library, that can establish arbitrary rules for itself. – IInspectable Mar 01 '23 at 20:56
  • @IInspectable *It still has to follow language rules regardless* Oh, cut that crap out. [Microsoft doesn't care about strict compliance to the C standard](https://learn.microsoft.com/en-us/cpp/overview/visual-cpp-language-conformance?view=msvc-170). Where are C99's **mandatory** VLAs? [No, Microsoft **doesn't** care](https://www.open-std.org/jtc1/sc22/wg14/www/docs/n1967.htm#impementations) " As a result of the numerous deviations from the specification the Microsoft implementation cannot be considered conforming or portable." – Andrew Henle Mar 01 '23 at 22:31
  • @IInspectable "They have to comply with the C standard" is a **garbage** argument when I comes to Microsoft. VLAs were mandatory **last CENTURY**, and this **century** is 1/4 over already. "They have to comply with the C standard" is whiny bullcrap when it comes to Microsoft when Microsoft only does that in ways that falsely imply a widespread, portable function is "deprecated". That argument is doubly risible given Microsoft applies the same misleading "deprecation" to C standard functions such as `strcpy()`. – Andrew Henle Mar 01 '23 at 22:37
  • @IInspectable Riddle me this, Batman: [Why does Microsoft "deprecate" the **standard C function** `strcpy()`?](https://stackoverflow.com/questions/4012222/c-strcpy-gives-a-warning-c4996) Why do Microsoft's "deprecations" **always** seem to go in the direction of FUD against standard, portable code and in favor of Microsoft-only solutions? `mkdir()`? "Oooh, that violates the C standard!" "Umm, `strcpy()`, `fopen()`, and a whole lot more functions are **in the C standard**." It's gonna be interesting to see how you move the goalposts - again. – Andrew Henle Mar 01 '23 at 22:39
  • @IInspectable There's no way you can claim Microsoft cares about C standard compliance when they misleadingly "deprecate" functions **required** to exist by the C standard since C89 such as `fopen()` and `strcpy()` given those functions **are not** deprecated in any version of the C standard ever published - or planned to be published. – Andrew Henle Mar 01 '23 at 22:49
  • @AndrewHenle I'd cover those points, but, honestly, this starts to read a lot like a *"YOU issue"* rather than a *"THEM issue"*. Now, in case you missed somewhat recent news, we're in the process of deprecating C as an acceptable tool to describe computer programs (see [EO 14028](https://www.whitehouse.gov/briefing-room/presidential-actions/2021/05/12/executive-order-on-improving-the-nations-cybersecurity/) and [NIST's response](https://www.nist.gov/itl/executive-order-14028-improving-nations-cybersecurity)). I'm positive that your beloved POSIX will find an honorable mention in history books. – IInspectable Mar 02 '23 at 16:24
  • @IInspectable Not one of your arguments holds water. `mkdir()` is functionally equivalent to `CreateDirectory()`, both are distributed with Windows, neither are in the C standard, but Microsoft only "deprecates" *portable* `mkdir()`. *we're in the process of deprecating C as an acceptable tool to describe computer programs* **BWAAAHH HAAAH HAAA!!!!** You're funny. Linus: "Pound sand! Linux kernel will remain C." You obviously have zero clue how much government infrastructure runs Linux. – Andrew Henle Mar 02 '23 at 17:04
  • @IInspectable Oh, yeah: [Windows kernel is mostly C, too](https://github.com/onein528/NT5.1). You: "I'd like to buy a clue, Pat!" – Andrew Henle Mar 02 '23 at 17:05
  • @IInspectable And good luck "deprecating" Java. Guess what? [The JDK is mostly written in C](https://github.com/openjdk/jdk). – Andrew Henle Mar 02 '23 at 17:17
  • @AndrewHenle Could you point me to the section in the ISO C specification that explains how issuing a warning affects conformance? As for portability, that's a moot point: `mkdir` cannot be made to work reliably on Windows anyway. – IInspectable Mar 03 '23 at 07:59
  • @IInspectable There go those goalposts again - just like I said. It's [just more Microsoft FUD](https://en.wikipedia.org/wiki/Fear,_uncertainty,_and_doubt#Microsoft): *At one point, Microsoft CEO Bill Gates sent a memo to a number of employees, reading "You never sent me a response on the question of what things an app would do that would make it run with MS-DOS and not run with DR-DOS" and "What the [user] is supposed to do is feel uncomfortable, and when he has bugs, suspect that the problem is DR-DOS and then go out to buy MS-DOS.* And read https://en.wikipedia.org/wiki/Halloween_documents – Andrew Henle Mar 03 '23 at 10:23
  • @AndrewHenle That doesn't exactly address the question asked. Could you try again? – IInspectable Mar 03 '23 at 10:27
  • @IInspectable ROFLMAO. You just stepped on your own crank with golf shoes and destroyed your entire "Microsoft must issue the warning in order to comply with the C standard". **There's no requirement in the C standard to issue such a warning** – Andrew Henle Mar 03 '23 at 10:34
  • @AndrewHenle Right. There is no such requirement. But that wasn't what I suggested, either. I was asking, which portion in the ISO C Standard describes that issuing a warning renders a compiler non-conforming. Which you repeatedly suggested were the case. So, could you try again? – IInspectable Mar 03 '23 at 10:39
  • @IInspectable *But that wasn't what I suggested, either.* You didn't merely "suggest" it, you stated it clearly. You specifically said Microsoft had to issue a warning to "stay in-spec": *just because Microsoft doesn't ship a fully conforming C99 compiler, does that mean they shouldn't stay in-spec for the parts they have implemented?* That's clearly stating not issuing a warning would be "out-of-spec". Move, goalpost, move! – Andrew Henle Mar 03 '23 at 11:05
  • @AndrewHenle Moving a function that isn't part of C into a namespace reserved for non-standard extensions is what's required. Issuing a warning is not required. Regardless, you still haven't produced an answer to the question: Which part of the ISO C Standard covers that issuing a warning renders a compiler non-conforming? Would you like to try again? – IInspectable Mar 04 '23 at 07:53
  • @IInspectable **You** have been the one claiming that the warning was **REQUIRED** for Microsoft to be compliant. You were **WRONG**. Nor have you yet explained why putting `mkdir()` into the namespace justifies a warning while putting `CreateDirectory()` into that same name space does NOT. You have been all over the place with flat-out wrong claims like *It isn't part of of any language implementation nor language support library, and doesn't ship with Microsoft's C or C++ compiler. mkdir, on the other hand, does.* Nor have you bothered to address Microsoft's risible "deprecation" of `fopen` – Andrew Henle Mar 04 '23 at 22:42
  • @IInspectable Come on, explain the "deprecation" of `fopen()` with respect to its status as a **required** function per every version of the C standard ever published in draft or final form. I **can** explain it: it's **FUD**, just like the "deprecation" of `mkdir()`. And guess what? That explanation is **CONSISTENT** with why Microsoft "deprecates" `mkdir()` - **FUD** thrown against portable, non-Microsoft code. And it's consistent with Microsoft's behavior over multiple **DECADES**. – Andrew Henle Mar 04 '23 at 22:43
  • @IInspectable I don't have to justify any non-warning - you have to justify the "deprecation" warning for `mkdir()` - and `fopen()`. I'm just pointing out the Microsoft "deprecates" portable code **even when those functions must be present per the C standard and will likely NEVER be removed**. – Andrew Henle Mar 04 '23 at 22:52
  • @AndrewHenle You have started hallucinating now, and I doubt you have a genuine interest in learning. If that is wrong, you should contact Microsoft and ask the respective team why they decided to issue a warning when using `fopen` (I'm guessing it is because C isn't entirely confident that [`fopen`](https://en.cppreference.com/w/c/io/fopen) should be used anymore either). Now, obviously, `fopen` will never be removed, and [C will never stop you from making mistakes](https://thephd.dev/your-c-compiler-and-standard-library-will-not-help-you). Good luck if C is your First Love. – IInspectable Mar 05 '23 at 11:23
  • @IInspectable Nothing like giving up and failing. [Hallucinating](https://en.wikipedia.org/wiki/Fear,_uncertainty,_and_doubt#Microsoft), you say? ROFLMAO. If it's too hard for you to write correct code without your language doing a lot of hand-holding for you, that's **your** problem. Lemme guess - you're *skeered* of power tools, and a chainsaw literally makes your heart stop! *C will never stop you from making mistakes.* Awwww, aren't you adorbs? **Some of us don't need the help**. We write things like Linux and Windows kernels and JVMs. **YOU** live in the world **WE** create. – Andrew Henle Mar 05 '23 at 13:02
  • @AndrewHenle *" If it's too hard for you to write correct code without your language doing a lot of hand-holding for you, that's **your** problem."* - That's correct, and I acknowledge that. *"**Some of us don't need the help.**"* - Now, *that* is wrong. We have 50 years' worth of data, and that data speaks a clear language: **We** cannot write correct C code. Feel free to challenge that, but do keep it civil while making a fool out of yourself. – IInspectable Mar 05 '23 at 18:36
  • @IInspectable Damn, those Linux and Windows kernels and JVMs all written in C must not be able to run for **years** at a time. [Oh, wait, you're **WRONG** again](https://www.reddit.com/r/linux/comments/r411j/what_is_the_longest_uptime_you_have_ever_seen/). You are **totes** adorbs. You appear to be the type of programmer that would be put out of work if **real** engineering standards were applied to writing code the same way it's done for designing bridges. I wouldn't be. – Andrew Henle Mar 05 '23 at 19:12
  • @AndrewHenle *"Damn, those Linux and Windows kernels and JVMs all written in C must not be able to run for **years** at a time."* - Oh, they do. That's not hard. Like, at all. Keeping systems exercising \[L|R\]CE's for years is so trivial, even **I** could do it. If that is your understanding of what reliability (sorry, *"**real** engineering"*) means, then that explains a lot. Now, my understanding of reliability is somewhat different. I would expect those systems to *also* remain consistent. None of the examples you provided seem to [meet that criteria](https://cve.mitre.org/). – IInspectable Mar 05 '23 at 19:35
  • @IInspectable It's amusing that your days-long desperate defense of Microsoft's throwing FUD at portable code has left you with nowhere to turn but to attack the very foundations of the environment you make a living in. You've figurately thrown rocks at everything you can think of in order to avoid admitting something the entire world **knows**: **Microsoft throws FUD at portable non-Microsoft code**. They've done it for decades, going so far as to provide under-the-table funding for SCO in SCO v. IBM. The fact that they use their compiler to continue to throw FUD should be no surprise. – Andrew Henle Mar 05 '23 at 19:46
  • @IInspectable When you gonna fill us all in on why Microsoft "deprecates" C-standard-**required** `strcpy()`? It's no less safe than `strcpy_s()` because if you know your string lengths, `strcpy()` is perfectly safe, and if you *don't* know the string lengths `strcpy_s()` can't help you. Or `fopen()`? It's because of **FUD**. – Andrew Henle Mar 05 '23 at 19:52
  • @AndrewHenle *"When you gonna fill us all in on why Microsoft 'deprecates' C-standard-**required** `strcpy()`?"* - Yes, that was **mean**. I mean, ***how*** could they. Them meanies. That's bad. Very bad of them. Sort of. Though, maybe not as bad as ISO C realizing, that `strcpy` was broken. So they "fixed" it, with `strncpy`. And then, when they realized, that `strncpy` was broken, for a different reason, they fixed it again (`strncpy_s`). Still, I find it **unreasonable** of Microsoft to issue a warning, when we wish to call `strcpy`. Yes, Andrew, that was a *very* bad move. I agree. – IInspectable Mar 05 '23 at 20:19
  • @IInspectable Wow. You are **soooooo** wrong. [Stepping on your own crank, **AGAIN**](https://port70.net/~nsz/c/c89/rationale/d11.html#strncpy-4-11-2-4): – Andrew Henle Mar 05 '23 at 20:21
  • @IInspectable "strncpy was initially introduced into the C library to deal with fixed-length name fields in structures such as directory entries. Such fields are not used in the same way as strings: the trailing null is unnecessary for a maximum-length field, and setting trailing bytes for shorter names to null assures efficient field-wise comparisons. strncpy is not by origin a ``bounded strcpy,'' and the Committee has preferred to recognize existing practice rather than alter the function to better suit it to such use. " – Andrew Henle Mar 05 '23 at 20:21
  • @IInspectable I am literally laughing at you. You got it **WRONG**. **AGAIN**. `strncpy()` was originally developed to **FILL** fixed-length fields. Ooops. See https://softwareengineering.stackexchange.com/questions/438025/what-was-the-original-purpose-of-c-strncpy-function too. – Andrew Henle Mar 05 '23 at 20:23
  • @IInspectable And I'll say it again: there's nothing wring with `strcpy()` if you properly track the length of your strings. If, on the other hand, you're incompetent... – Andrew Henle Mar 05 '23 at 20:26
  • @AndrewHenle Relax, dude. You may have missed it. I'm **totally** with you, that Microsoft should **not** have allowed that to happen. Warning on use of `strcpy` ***is*** bad. If this is something that matters to you as much as it matters to me, could you start a petition to have Bill Gates removed as a CEO from Microsoft? I would absolutely sign that. This Ballmer guy seems legit. Maybe he can step in? – IInspectable Mar 05 '23 at 20:34

2 Answers2

3

At least this problem

Mis-matched specifiers

To sprintf() a %, the format needs %%.

// sprintf(infoPath, "C:\\Users\\%username%\\Desktop\\%s", whoami);
sprintf(infoPath, "C:\\Users\\%%username%%\\Desktop\\%s", whoami);

Save time: enable all compiler warnings

chux - Reinstate Monica
  • 143,097
  • 13
  • 135
  • 256
2

The root problem is this line:

sprintf(infoPath, "C:\\Users\\%username%\\Desktop\\%s", whoami);

sprintf() will interpret %u as a placeholder taking in an unsigned int input value (which of course is not what you are providing), and will then fail on %\ as an invalid placeholder.

To print out a literal % character, you need to use the %% placeholder, eg:

sprintf(infoPath, "C:\\Users\\%%username%%\\Desktop\\%s", whoami);

However, even with this fix, you will still run into a problem with _mkdir(). When you pass in the (fixed) formatted string, _mkdir() will not translate the %username% environment variable, like you are expecting. You need to call ExpandEnvironmentStringsA() before giving the string to _mkdir(), eg:

char infoPath[1000];
sprintf(infoPath, "C:\\Users\\%%username%%\\Desktop\\%s", whoami);

char expandedInfoPath[1000];
ExpandEnvironmentStringsA(infoPath, expandedInfoPath, 1000);

_mkdir(expandedInfoPath)

That being said, your whole approach to preparing the path string is completely wrong. The correct way to get the path to the user's Desktop folder is to ask Windows for the path, by using either SHGetFolderPathA(CSIDL_DESKTOPDIRECTORY) or SHGetKnownFolderPath(FOLDERID_Desktop) instead, eg:

SHGetFolderPathA(NULL, CSIDL_DESKTOPDIRECTORY, NULL, SHGFP_TYPE_CURRENT, infoPath);
PathAppendA(infoPath, whoami);
_mkdir(infoPath)

The location of user profiles can/does differ from one Windows version to another, and even the location of the desktop itself can be customized by the user in the Registry.

Remy Lebeau
  • 555,201
  • 31
  • 458
  • 770