0

is there a way to get the application directory while being in dllinit / loader lock? Currently I know only the way presented here. Since this approach potentially loads the Shell32.dll, I assume it is not safe during dllinit.

Any advice / other way to do it?


Clarification: I'm searching the AppData directory, not for the directory where the executable resides.

Community
  • 1
  • 1
Tobias Langner
  • 10,634
  • 6
  • 46
  • 76
  • 2
    You really aren't supposed to do much of anything while in DllInit. Why can't you extract that code out of the initialization method? Why do you need to read/write a directory to initialize the DLL? – Cody Gray - on strike Jul 10 '13 at 07:39
  • 2
    The question is too vague. You can probably use the APPDATA environment variable, if that's what you really want. It is also likely that whatever you actually do with the string is going to get you into trouble. – Hans Passant Jul 10 '13 at 10:08
  • I try to implement the feature toggle pattern. Since I want to be able to toggle code in static initialization code, the code should not deadlock in the presence of a loader lock. The directory is used to find a common location for the configuration file that is used to decide whether a toggle is on or off. – Tobias Langner Jul 10 '13 at 10:26
  • @HansPassant: yes, you have to be careful with string operations. I already noticed that. – Tobias Langner Jul 10 '13 at 10:29
  • 2
    Well, what are you going to do when you actually find that config file and it contains bad data? You have zero options to report this problem in a meaningful way. Your DLL will just misbehave with no way for anybody to figure out why. If you don't want to add an Initialize() function then lazily load the config file the first time you need to know what it contains, in one of the other exported functions. – Hans Passant Jul 10 '13 at 10:34
  • actually, there are 3 things that can be done - all are meaningful in that context: 1. report via Outputdebugstring. 2. all features are set to false (this is the default) 3. provide an interface that allows the user to read&log from his api once the dlls are loaded. Lazy loading is actually what I'm doing, but if you toggle some code in constructors of static variables, the ini file is loaded during CRT init - which is done in dll-init (of the dll containing the static variables) – Tobias Langner Jul 10 '13 at 12:33

3 Answers3

2

If you are looking for the application directory (where the EXE resides) you can use GetModuleFileName and then use _splitpath. This is in kernel32, so no other DLL gets loaded.

Jochen Kalmbach
  • 3,549
  • 17
  • 18
  • The link in the question suggests he's looking for the AppData directory, not the directory in which the application resides. Otherwise, this is a good solution. – Cody Gray - on strike Jul 10 '13 at 07:41
  • Yes, the question is unclear. If they want to have the AppData Directory he should either use a "Init" function or start a thread... – Jochen Kalmbach Jul 10 '13 at 07:55
2

You can use ExpandEnvironmentStrings or GetEnvironmentVariable with %APPDATA% (or %LOCALAPPDATA% depending on what path do you want to get). Those functions are from kernel32.dll.

Sergey Podobry
  • 7,101
  • 1
  • 41
  • 51
0

You can use SHGetFolderPath (with CSIDL_APPDATA or CSIDL_LOCAL_APPDATA) or SHGetKnownFolderPath (with FOLDERID_RoamingAppData/FOLDERID_LocalAppData).

But I would recommend using registry instead of flag files.

Igor Skochinsky
  • 24,629
  • 2
  • 72
  • 109
  • 1
    using other dlls as kernel32.dll can cause a deadlock in dll init with the loader lock. Your proposed solutions load either shell32.dll or advapi32.dll. If they are not already loaded, the loade lock will bite you. Reading files on the other hand is safe. – Tobias Langner Jul 10 '13 at 12:29
  • If you use static imports (i.e. not GetProcAddress or delayed imports), the DLLs will be loaded by the kernel loader before it calls your DllMain. Why not try before dismissing the solution? – Igor Skochinsky Jul 10 '13 at 13:04
  • 1
    the problem is, my dll is loaded by dllmain of another dll. If my dll then tries to load another dll, it'll fail because of the loader lock. – Tobias Langner Jul 10 '13 at 13:41
  • @TobiasLangner I don't see how that DLL would be able to load your DLL but not any dependencies. If it's importing your DLL implicitly, then everything will work. If it's using `LoadLibrary` in its `DllMain` to do it, [it's playing with fire](http://blogs.msdn.com/b/oleglv/archive/2003/10/28/56142.aspx) anyway. – Igor Skochinsky Jul 10 '13 at 15:27
  • Calling in the DllMain any functions from dlls other than kernel32 or ntdll is dangerous. Personally I faced registry read failures using advapi32 and had to switch to ntdll. – Sergey Podobry Jul 11 '13 at 06:16