1+ // --------------------------------------------------------------------------------------
2+ // File: FindMedia.h
3+ //
4+ // Helper function to find the location of a media file for Windows desktop apps
5+ // since they lack appx packaging support.
6+ //
7+ // THIS CODE AND INFORMATION IS PROVIDED "AS IS" WITHOUT WARRANTY OF
8+ // ANY KIND, EITHER EXPRESSED OR IMPLIED, INCLUDING BUT NOT LIMITED TO
9+ // THE IMPLIED WARRANTIES OF MERCHANTABILITY AND/OR FITNESS FOR A
10+ // PARTICULAR PURPOSE.
11+ //
12+ // Copyright (c) Microsoft Corporation. All rights reserved.
13+ // -------------------------------------------------------------------------------------
14+
15+ #pragma once
16+
17+ #if defined(WINAPI_FAMILY) && (WINAPI_FAMILY != WINAPI_FAMILY_DESKTOP_APP)
18+ #error This header only works with Windows desktop apps
19+ #endif
20+
21+ #include < exception>
22+ #include < string.h>
23+
24+
25+ namespace DX
26+ {
27+ inline void FindMediaFile (_Out_writes_(cchDest) wchar_t* strDestPath, _In_ int cchDest, _In_z_ const wchar_t* strFilename)
28+ {
29+ bool bFound = false ;
30+
31+ if (!strFilename || strFilename[0 ] == 0 || !strDestPath || cchDest < 10 )
32+ throw std::invalid_argument (" FindMediaFile" );
33+
34+ // Get the exe name, and exe path
35+ wchar_t strExePath[MAX_PATH] = {};
36+ wchar_t strExeName[MAX_PATH] = {};
37+ wchar_t * strLastSlash = nullptr ;
38+ GetModuleFileName (nullptr , strExePath, MAX_PATH);
39+ strExePath[MAX_PATH - 1 ] = 0 ;
40+ strLastSlash = wcsrchr (strExePath, TEXT (' \\ ' ));
41+ if (strLastSlash)
42+ {
43+ wcscpy_s (strExeName, MAX_PATH, &strLastSlash[1 ]);
44+
45+ // Chop the exe name from the exe path
46+ *strLastSlash = 0 ;
47+
48+ // Chop the .exe from the exe name
49+ strLastSlash = wcsrchr (strExeName, TEXT (' .' ));
50+ if (strLastSlash)
51+ *strLastSlash = 0 ;
52+ }
53+
54+ wcscpy_s (strDestPath, cchDest, strFilename);
55+ if (GetFileAttributes (strDestPath) != 0xFFFFFFFF )
56+ return ;
57+
58+ // Search all parent directories starting at .\ and using strFilename as the leaf name
59+ wchar_t strLeafName[MAX_PATH] = {};
60+ wcscpy_s (strLeafName, MAX_PATH, strFilename);
61+
62+ wchar_t strFullPath[MAX_PATH] = {};
63+ wchar_t strFullFileName[MAX_PATH] = {};
64+ wchar_t strSearch[MAX_PATH] = {};
65+ wchar_t * strFilePart = nullptr ;
66+
67+ GetFullPathName (strExePath, MAX_PATH, strFullPath, &strFilePart);
68+ if (!strFilePart)
69+ throw std::exception (" FindMediaFile" );
70+
71+ while (strFilePart && *strFilePart != ' \0 ' )
72+ {
73+ swprintf_s (strFullFileName, MAX_PATH, L" %ls\\ %ls" , strFullPath, strLeafName);
74+ if (GetFileAttributes (strFullFileName) != 0xFFFFFFFF )
75+ {
76+ wcscpy_s (strDestPath, cchDest, strFullFileName);
77+ bFound = true ;
78+ break ;
79+ }
80+
81+ swprintf_s (strFullFileName, MAX_PATH, L" %ls\\ %ls\\ %ls" , strFullPath, strExeName, strLeafName);
82+ if (GetFileAttributes (strFullFileName) != 0xFFFFFFFF )
83+ {
84+ wcscpy_s (strDestPath, cchDest, strFullFileName);
85+ bFound = true ;
86+ break ;
87+ }
88+
89+ swprintf_s (strSearch, MAX_PATH, L" %ls\\ .." , strFullPath);
90+ GetFullPathName (strSearch, MAX_PATH, strFullPath, &strFilePart);
91+ }
92+ if (bFound)
93+ return ;
94+
95+ // On failure, return the file as the path but also return an error code
96+ wcscpy_s (strDestPath, cchDest, strFilename);
97+
98+ throw std::exception (" File not found" );
99+ }
100+ }
0 commit comments