* Sync up to trunk head (r64921).
[reactos.git] / dll / win32 / fmifs / init.c
1 /*
2 * COPYRIGHT: See COPYING in the top level directory
3 * PROJECT: File Management IFS Utility functions
4 * FILE: reactos/dll/win32/fmifs/init.c
5 * PURPOSE: Initialisation
6 *
7 * PROGRAMMERS: Emanuele Aliberti
8 * Hervé Poussineau (hpoussin@reactos.org)
9 */
10
11 #include "precomp.h"
12
13 #include <winreg.h>
14 #include <ndk/cmfuncs.h>
15 #include <ndk/obfuncs.h>
16
17 static BOOLEAN FmIfsInitialized = FALSE;
18 LIST_ENTRY ProviderListHead;
19
20 PIFS_PROVIDER
21 GetProvider(
22 IN PWCHAR FileSystem)
23 {
24 PLIST_ENTRY ListEntry;
25 PIFS_PROVIDER Provider;
26
27 ListEntry = ProviderListHead.Flink;
28 while (ListEntry != &ProviderListHead)
29 {
30 Provider = CONTAINING_RECORD(ListEntry, IFS_PROVIDER, ListEntry);
31 if (_wcsicmp(Provider->Name, FileSystem) == 0)
32 return Provider;
33 ListEntry = ListEntry->Flink;
34 }
35
36 /* Provider not found */
37 return NULL;
38 }
39
40
41 static
42 BOOLEAN
43 AddProvider(
44 IN PCUNICODE_STRING FileSystem,
45 IN PWCHAR DllFile)
46 {
47 PIFS_PROVIDER Provider = NULL;
48 ULONG RequiredSize;
49 HMODULE hMod = NULL;
50 BOOLEAN ret = FALSE;
51
52 hMod = LoadLibraryW(DllFile);
53 if (!hMod)
54 goto cleanup;
55
56 RequiredSize = FIELD_OFFSET(IFS_PROVIDER, Name)
57 + FileSystem->Length + sizeof(UNICODE_NULL);
58 Provider = (PIFS_PROVIDER)RtlAllocateHeap(
59 RtlGetProcessHeap(),
60 0,
61 RequiredSize);
62 if (!Provider)
63 goto cleanup;
64 RtlZeroMemory(Provider, RequiredSize);
65
66 /* Get function pointers */
67 Provider->ChkdskEx = (CHKDSKEX)GetProcAddress(hMod, "ChkdskEx");
68 //Provider->Extend = (EXTEND)GetProcAddress(hMod, "Extend");
69 Provider->FormatEx = (FORMATEX)GetProcAddress(hMod, "FormatEx");
70
71 RtlCopyMemory(Provider->Name, FileSystem->Buffer, FileSystem->Length);
72
73 InsertTailList(&ProviderListHead, &Provider->ListEntry);
74 ret = TRUE;
75
76 cleanup:
77 if (!ret)
78 {
79 if (hMod)
80 FreeLibrary(hMod);
81 if (Provider)
82 RtlFreeHeap(RtlGetProcessHeap(), 0, Provider);
83 }
84 return ret;
85 }
86
87 static
88 BOOLEAN
89 InitializeFmIfsOnce(VOID)
90 {
91 OBJECT_ATTRIBUTES ObjectAttributes;
92 UNICODE_STRING RegistryPath
93 = RTL_CONSTANT_STRING(L"\\REGISTRY\\Machine\\SOFTWARE\\ReactOS\\ReactOS\\CurrentVersion\\IFS");
94 HANDLE hKey = NULL;
95 PKEY_VALUE_FULL_INFORMATION Buffer;
96 ULONG BufferSize = sizeof(KEY_VALUE_FULL_INFORMATION) + MAX_PATH;
97 ULONG RequiredSize;
98 ULONG i = 0;
99 UNICODE_STRING Name;
100 UNICODE_STRING Data;
101 NTSTATUS Status;
102
103 InitializeListHead(&ProviderListHead);
104
105 /* Read IFS providers from HKLM\SOFTWARE\ReactOS\ReactOS\CurrentVersion\IFS */
106 InitializeObjectAttributes(&ObjectAttributes, &RegistryPath, 0, NULL, NULL);
107 Status = NtOpenKey(&hKey, KEY_QUERY_VALUE, &ObjectAttributes);
108 if (Status == STATUS_OBJECT_NAME_NOT_FOUND)
109 return TRUE;
110 else if (!NT_SUCCESS(Status))
111 return FALSE;
112
113 Buffer = (PKEY_VALUE_FULL_INFORMATION)RtlAllocateHeap(
114 RtlGetProcessHeap(),
115 0,
116 BufferSize);
117 if (!Buffer)
118 {
119 NtClose(hKey);
120 return FALSE;
121 }
122
123 while (TRUE)
124 {
125 Status = NtEnumerateValueKey(
126 hKey,
127 i++,
128 KeyValueFullInformation,
129 Buffer,
130 BufferSize,
131 &RequiredSize);
132 if (Status == STATUS_BUFFER_OVERFLOW)
133 continue;
134 else if (!NT_SUCCESS(Status))
135 break;
136 else if (Buffer->Type != REG_SZ)
137 continue;
138
139 Name.Length = Name.MaximumLength = Buffer->NameLength;
140 Name.Buffer = Buffer->Name;
141 Data.Length = Data.MaximumLength = Buffer->DataLength;
142 Data.Buffer = (PWCHAR)((ULONG_PTR)Buffer + Buffer->DataOffset);
143 if (Data.Length > sizeof(WCHAR) && Data.Buffer[Data.Length / sizeof(WCHAR) - 1] == UNICODE_NULL)
144 Data.Length -= sizeof(WCHAR);
145
146 AddProvider(&Name, Data.Buffer);
147 }
148
149 NtClose(hKey);
150 RtlFreeHeap(RtlGetProcessHeap(), 0, Buffer);
151 return TRUE;
152 }
153
154 /* FMIFS.8 */
155 BOOLEAN
156 NTAPI
157 InitializeFmIfs(
158 IN PVOID hinstDll,
159 IN DWORD dwReason,
160 IN PVOID reserved)
161 {
162 switch (dwReason)
163 {
164 case DLL_PROCESS_ATTACH:
165 if (FmIfsInitialized == FALSE)
166 {
167 if (InitializeFmIfsOnce() == FALSE)
168 {
169 return FALSE;
170 }
171
172 FmIfsInitialized = TRUE;
173 }
174 break;
175
176 case DLL_THREAD_ATTACH:
177 break;
178
179 case DLL_THREAD_DETACH:
180 break;
181
182 case DLL_PROCESS_DETACH:
183 break;
184 }
185
186 return TRUE;
187 }
188
189 /* EOF */