xpcom/build/PoisonIOInterposerWin.cpp

Wed, 31 Dec 2014 06:09:35 +0100

author
Michael Schloh von Bennewitz <michael@schloh.com>
date
Wed, 31 Dec 2014 06:09:35 +0100
changeset 0
6474c204b198
permissions
-rw-r--r--

Cloned upstream origin tor-browser at tor-browser-31.3.0esr-4.5-1-build1
revision ID fc1c9ff7c1b2defdbc039f12214767608f46423f for hacking purpose.

michael@0 1 /* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */
michael@0 2 /* vim:set ts=2 sw=2 sts=2 ci et: */
michael@0 3 /* This Source Code Form is subject to the terms of the Mozilla Public
michael@0 4 * License, v. 2.0. If a copy of the MPL was not distributed with this
michael@0 5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
michael@0 6
michael@0 7 #include "PoisonIOInterposer.h"
michael@0 8
michael@0 9 #include <algorithm>
michael@0 10 #include <stdio.h>
michael@0 11 #include <vector>
michael@0 12
michael@0 13 #include <io.h>
michael@0 14 #include <windows.h>
michael@0 15 #include <winternl.h>
michael@0 16
michael@0 17 #include "mozilla/Assertions.h"
michael@0 18 #include "mozilla/FileUtilsWin.h"
michael@0 19 #include "mozilla/IOInterposer.h"
michael@0 20 #include "mozilla/Mutex.h"
michael@0 21 #include "mozilla/TimeStamp.h"
michael@0 22 #include "nsTArray.h"
michael@0 23 #include "nsWindowsDllInterceptor.h"
michael@0 24 #include "plstr.h"
michael@0 25
michael@0 26 using namespace mozilla;
michael@0 27
michael@0 28 namespace {
michael@0 29
michael@0 30 // Keep track of poisoned state. Notice that there is no reason to lock access
michael@0 31 // to this variable as it's only changed in InitPoisonIOInterposer and
michael@0 32 // ClearPoisonIOInterposer which may only be called on the main-thread when no
michael@0 33 // other threads are running.
michael@0 34 static bool sIOPoisoned = false;
michael@0 35
michael@0 36 /************************ Internal NT API Declarations ************************/
michael@0 37
michael@0 38 /*
michael@0 39 * Function pointer declaration for internal NT routine to create/open files.
michael@0 40 * For documentation on the NtCreateFile routine, see MSDN.
michael@0 41 */
michael@0 42 typedef NTSTATUS (NTAPI *NtCreateFileFn)(
michael@0 43 OUT PHANDLE aFileHandle,
michael@0 44 IN ACCESS_MASK aDesiredAccess,
michael@0 45 IN POBJECT_ATTRIBUTES aObjectAttributes,
michael@0 46 OUT PIO_STATUS_BLOCK aIoStatusBlock,
michael@0 47 IN PLARGE_INTEGER aAllocationSize,
michael@0 48 IN ULONG aFileAttributes,
michael@0 49 IN ULONG aShareAccess,
michael@0 50 IN ULONG aCreateDisposition,
michael@0 51 IN ULONG aCreateOptions,
michael@0 52 IN PVOID aEaBuffer,
michael@0 53 IN ULONG aEaLength
michael@0 54 );
michael@0 55
michael@0 56 /**
michael@0 57 * Function pointer declaration for internal NT routine to read data from file.
michael@0 58 * For documentation on the NtReadFile routine, see ZwReadFile on MSDN.
michael@0 59 */
michael@0 60 typedef NTSTATUS (NTAPI *NtReadFileFn)(
michael@0 61 IN HANDLE aFileHandle,
michael@0 62 IN HANDLE aEvent,
michael@0 63 IN PIO_APC_ROUTINE aApc,
michael@0 64 IN PVOID aApcCtx,
michael@0 65 OUT PIO_STATUS_BLOCK aIoStatus,
michael@0 66 OUT PVOID aBuffer,
michael@0 67 IN ULONG aLength,
michael@0 68 IN PLARGE_INTEGER aOffset,
michael@0 69 IN PULONG aKey
michael@0 70 );
michael@0 71
michael@0 72 /**
michael@0 73 * Function pointer declaration for internal NT routine to read data from file.
michael@0 74 * No documentation exists, see wine sources for details.
michael@0 75 */
michael@0 76 typedef NTSTATUS (NTAPI* NtReadFileScatterFn)(
michael@0 77 IN HANDLE aFileHandle,
michael@0 78 IN HANDLE aEvent,
michael@0 79 IN PIO_APC_ROUTINE aApc,
michael@0 80 IN PVOID aApcCtx,
michael@0 81 OUT PIO_STATUS_BLOCK aIoStatus,
michael@0 82 IN FILE_SEGMENT_ELEMENT* aSegments,
michael@0 83 IN ULONG aLength,
michael@0 84 IN PLARGE_INTEGER aOffset,
michael@0 85 IN PULONG aKey
michael@0 86 );
michael@0 87
michael@0 88 /**
michael@0 89 * Function pointer declaration for internal NT routine to write data to file.
michael@0 90 * For documentation on the NtWriteFile routine, see ZwWriteFile on MSDN.
michael@0 91 */
michael@0 92 typedef NTSTATUS (NTAPI *NtWriteFileFn)(
michael@0 93 IN HANDLE aFileHandle,
michael@0 94 IN HANDLE aEvent,
michael@0 95 IN PIO_APC_ROUTINE aApc,
michael@0 96 IN PVOID aApcCtx,
michael@0 97 OUT PIO_STATUS_BLOCK aIoStatus,
michael@0 98 IN PVOID aBuffer,
michael@0 99 IN ULONG aLength,
michael@0 100 IN PLARGE_INTEGER aOffset,
michael@0 101 IN PULONG aKey
michael@0 102 );
michael@0 103
michael@0 104 /**
michael@0 105 * Function pointer declaration for internal NT routine to write data to file.
michael@0 106 * No documentation exists, see wine sources for details.
michael@0 107 */
michael@0 108 typedef NTSTATUS (NTAPI *NtWriteFileGatherFn)(
michael@0 109 IN HANDLE aFileHandle,
michael@0 110 IN HANDLE aEvent,
michael@0 111 IN PIO_APC_ROUTINE aApc,
michael@0 112 IN PVOID aApcCtx,
michael@0 113 OUT PIO_STATUS_BLOCK aIoStatus,
michael@0 114 IN FILE_SEGMENT_ELEMENT* aSegments,
michael@0 115 IN ULONG aLength,
michael@0 116 IN PLARGE_INTEGER aOffset,
michael@0 117 IN PULONG aKey
michael@0 118 );
michael@0 119
michael@0 120 /**
michael@0 121 * Function pointer declaration for internal NT routine to flush to disk.
michael@0 122 * For documentation on the NtFlushBuffersFile routine, see ZwFlushBuffersFile
michael@0 123 * on MSDN.
michael@0 124 */
michael@0 125 typedef NTSTATUS (NTAPI *NtFlushBuffersFileFn)(
michael@0 126 IN HANDLE aFileHandle,
michael@0 127 OUT PIO_STATUS_BLOCK aIoStatusBlock
michael@0 128 );
michael@0 129
michael@0 130 typedef struct _FILE_NETWORK_OPEN_INFORMATION* PFILE_NETWORK_OPEN_INFORMATION;
michael@0 131 /**
michael@0 132 * Function pointer delaration for internal NT routine to query file attributes.
michael@0 133 * (equivalent to stat)
michael@0 134 */
michael@0 135 typedef NTSTATUS (NTAPI *NtQueryFullAttributesFileFn)(
michael@0 136 IN POBJECT_ATTRIBUTES aObjectAttributes,
michael@0 137 OUT PFILE_NETWORK_OPEN_INFORMATION aFileInformation
michael@0 138 );
michael@0 139
michael@0 140 /*************************** Auxiliary Declarations ***************************/
michael@0 141
michael@0 142 /**
michael@0 143 * RAII class for timing the duration of an I/O call and reporting the result
michael@0 144 * to the IOInterposeObserver API.
michael@0 145 */
michael@0 146 class WinIOAutoObservation : public IOInterposeObserver::Observation
michael@0 147 {
michael@0 148 public:
michael@0 149 WinIOAutoObservation(IOInterposeObserver::Operation aOp,
michael@0 150 HANDLE aFileHandle, const LARGE_INTEGER* aOffset)
michael@0 151 : IOInterposeObserver::Observation(aOp, sReference,
michael@0 152 !IsDebugFile(reinterpret_cast<intptr_t>(
michael@0 153 aFileHandle)))
michael@0 154 , mFileHandle(aFileHandle)
michael@0 155 , mHasQueriedFilename(false)
michael@0 156 , mFilename(nullptr)
michael@0 157 {
michael@0 158 if (mShouldReport) {
michael@0 159 mOffset.QuadPart = aOffset ? aOffset->QuadPart : 0;
michael@0 160 }
michael@0 161 }
michael@0 162
michael@0 163 WinIOAutoObservation(IOInterposeObserver::Operation aOp, nsAString& aFilename)
michael@0 164 : IOInterposeObserver::Observation(aOp, sReference)
michael@0 165 , mFileHandle(nullptr)
michael@0 166 , mHasQueriedFilename(false)
michael@0 167 , mFilename(nullptr)
michael@0 168 {
michael@0 169 if (mShouldReport) {
michael@0 170 nsAutoString dosPath;
michael@0 171 if (NtPathToDosPath(aFilename, dosPath)) {
michael@0 172 mFilename = ToNewUnicode(dosPath);
michael@0 173 mHasQueriedFilename = true;
michael@0 174 }
michael@0 175 mOffset.QuadPart = 0;
michael@0 176 }
michael@0 177 }
michael@0 178
michael@0 179 // Custom implementation of IOInterposeObserver::Observation::Filename
michael@0 180 const char16_t* Filename() MOZ_OVERRIDE;
michael@0 181
michael@0 182 ~WinIOAutoObservation()
michael@0 183 {
michael@0 184 Report();
michael@0 185 if (mFilename) {
michael@0 186 MOZ_ASSERT(mHasQueriedFilename);
michael@0 187 NS_Free(mFilename);
michael@0 188 mFilename = nullptr;
michael@0 189 }
michael@0 190 }
michael@0 191
michael@0 192 private:
michael@0 193 HANDLE mFileHandle;
michael@0 194 LARGE_INTEGER mOffset;
michael@0 195 bool mHasQueriedFilename;
michael@0 196 char16_t* mFilename;
michael@0 197 static const char* sReference;
michael@0 198 };
michael@0 199
michael@0 200 const char* WinIOAutoObservation::sReference = "PoisonIOInterposer";
michael@0 201
michael@0 202 // Get filename for this observation
michael@0 203 const char16_t* WinIOAutoObservation::Filename()
michael@0 204 {
michael@0 205 // If mHasQueriedFilename is true, then filename is already stored in mFilename
michael@0 206 if (mHasQueriedFilename) {
michael@0 207 return mFilename;
michael@0 208 }
michael@0 209
michael@0 210 nsAutoString utf16Filename;
michael@0 211 if (HandleToFilename(mFileHandle, mOffset, utf16Filename)) {
michael@0 212 // Heap allocate with leakable memory
michael@0 213 mFilename = ToNewUnicode(utf16Filename);
michael@0 214 }
michael@0 215 mHasQueriedFilename = true;
michael@0 216
michael@0 217 // Return filename
michael@0 218 return mFilename;
michael@0 219 }
michael@0 220
michael@0 221 /*************************** IO Interposing Methods ***************************/
michael@0 222
michael@0 223 // Function pointers to original functions
michael@0 224 static NtCreateFileFn gOriginalNtCreateFile;
michael@0 225 static NtReadFileFn gOriginalNtReadFile;
michael@0 226 static NtReadFileScatterFn gOriginalNtReadFileScatter;
michael@0 227 static NtWriteFileFn gOriginalNtWriteFile;
michael@0 228 static NtWriteFileGatherFn gOriginalNtWriteFileGather;
michael@0 229 static NtFlushBuffersFileFn gOriginalNtFlushBuffersFile;
michael@0 230 static NtQueryFullAttributesFileFn gOriginalNtQueryFullAttributesFile;
michael@0 231
michael@0 232 static NTSTATUS NTAPI InterposedNtCreateFile(
michael@0 233 PHANDLE aFileHandle,
michael@0 234 ACCESS_MASK aDesiredAccess,
michael@0 235 POBJECT_ATTRIBUTES aObjectAttributes,
michael@0 236 PIO_STATUS_BLOCK aIoStatusBlock,
michael@0 237 PLARGE_INTEGER aAllocationSize,
michael@0 238 ULONG aFileAttributes,
michael@0 239 ULONG aShareAccess,
michael@0 240 ULONG aCreateDisposition,
michael@0 241 ULONG aCreateOptions,
michael@0 242 PVOID aEaBuffer,
michael@0 243 ULONG aEaLength
michael@0 244 )
michael@0 245 {
michael@0 246 // Report IO
michael@0 247 const wchar_t* buf = aObjectAttributes ?
michael@0 248 aObjectAttributes->ObjectName->Buffer :
michael@0 249 L"";
michael@0 250 uint32_t len = aObjectAttributes ?
michael@0 251 aObjectAttributes->ObjectName->Length / sizeof(WCHAR) :
michael@0 252 0;
michael@0 253 nsDependentSubstring filename(buf, len);
michael@0 254 WinIOAutoObservation timer(IOInterposeObserver::OpCreateOrOpen, filename);
michael@0 255
michael@0 256 // Something is badly wrong if this function is undefined
michael@0 257 MOZ_ASSERT(gOriginalNtCreateFile);
michael@0 258
michael@0 259 // Execute original function
michael@0 260 return gOriginalNtCreateFile(
michael@0 261 aFileHandle,
michael@0 262 aDesiredAccess,
michael@0 263 aObjectAttributes,
michael@0 264 aIoStatusBlock,
michael@0 265 aAllocationSize,
michael@0 266 aFileAttributes,
michael@0 267 aShareAccess,
michael@0 268 aCreateDisposition,
michael@0 269 aCreateOptions,
michael@0 270 aEaBuffer,
michael@0 271 aEaLength
michael@0 272 );
michael@0 273 }
michael@0 274
michael@0 275 static NTSTATUS NTAPI InterposedNtReadFile(
michael@0 276 HANDLE aFileHandle,
michael@0 277 HANDLE aEvent,
michael@0 278 PIO_APC_ROUTINE aApc,
michael@0 279 PVOID aApcCtx,
michael@0 280 PIO_STATUS_BLOCK aIoStatus,
michael@0 281 PVOID aBuffer,
michael@0 282 ULONG aLength,
michael@0 283 PLARGE_INTEGER aOffset,
michael@0 284 PULONG aKey)
michael@0 285 {
michael@0 286 // Report IO
michael@0 287 WinIOAutoObservation timer(IOInterposeObserver::OpRead, aFileHandle, aOffset);
michael@0 288
michael@0 289 // Something is badly wrong if this function is undefined
michael@0 290 MOZ_ASSERT(gOriginalNtReadFile);
michael@0 291
michael@0 292 // Execute original function
michael@0 293 return gOriginalNtReadFile(
michael@0 294 aFileHandle,
michael@0 295 aEvent,
michael@0 296 aApc,
michael@0 297 aApcCtx,
michael@0 298 aIoStatus,
michael@0 299 aBuffer,
michael@0 300 aLength,
michael@0 301 aOffset,
michael@0 302 aKey
michael@0 303 );
michael@0 304 }
michael@0 305
michael@0 306 static NTSTATUS NTAPI InterposedNtReadFileScatter(
michael@0 307 HANDLE aFileHandle,
michael@0 308 HANDLE aEvent,
michael@0 309 PIO_APC_ROUTINE aApc,
michael@0 310 PVOID aApcCtx,
michael@0 311 PIO_STATUS_BLOCK aIoStatus,
michael@0 312 FILE_SEGMENT_ELEMENT* aSegments,
michael@0 313 ULONG aLength,
michael@0 314 PLARGE_INTEGER aOffset,
michael@0 315 PULONG aKey)
michael@0 316 {
michael@0 317 // Report IO
michael@0 318 WinIOAutoObservation timer(IOInterposeObserver::OpRead, aFileHandle, aOffset);
michael@0 319
michael@0 320 // Something is badly wrong if this function is undefined
michael@0 321 MOZ_ASSERT(gOriginalNtReadFileScatter);
michael@0 322
michael@0 323 // Execute original function
michael@0 324 return gOriginalNtReadFileScatter(
michael@0 325 aFileHandle,
michael@0 326 aEvent,
michael@0 327 aApc,
michael@0 328 aApcCtx,
michael@0 329 aIoStatus,
michael@0 330 aSegments,
michael@0 331 aLength,
michael@0 332 aOffset,
michael@0 333 aKey
michael@0 334 );
michael@0 335 }
michael@0 336
michael@0 337 // Interposed NtWriteFile function
michael@0 338 static NTSTATUS NTAPI InterposedNtWriteFile(
michael@0 339 HANDLE aFileHandle,
michael@0 340 HANDLE aEvent,
michael@0 341 PIO_APC_ROUTINE aApc,
michael@0 342 PVOID aApcCtx,
michael@0 343 PIO_STATUS_BLOCK aIoStatus,
michael@0 344 PVOID aBuffer,
michael@0 345 ULONG aLength,
michael@0 346 PLARGE_INTEGER aOffset,
michael@0 347 PULONG aKey)
michael@0 348 {
michael@0 349 // Report IO
michael@0 350 WinIOAutoObservation timer(IOInterposeObserver::OpWrite, aFileHandle,
michael@0 351 aOffset);
michael@0 352
michael@0 353 // Something is badly wrong if this function is undefined
michael@0 354 MOZ_ASSERT(gOriginalNtWriteFile);
michael@0 355
michael@0 356 // Execute original function
michael@0 357 return gOriginalNtWriteFile(
michael@0 358 aFileHandle,
michael@0 359 aEvent,
michael@0 360 aApc,
michael@0 361 aApcCtx,
michael@0 362 aIoStatus,
michael@0 363 aBuffer,
michael@0 364 aLength,
michael@0 365 aOffset,
michael@0 366 aKey
michael@0 367 );
michael@0 368 }
michael@0 369
michael@0 370 // Interposed NtWriteFileGather function
michael@0 371 static NTSTATUS NTAPI InterposedNtWriteFileGather(
michael@0 372 HANDLE aFileHandle,
michael@0 373 HANDLE aEvent,
michael@0 374 PIO_APC_ROUTINE aApc,
michael@0 375 PVOID aApcCtx,
michael@0 376 PIO_STATUS_BLOCK aIoStatus,
michael@0 377 FILE_SEGMENT_ELEMENT* aSegments,
michael@0 378 ULONG aLength,
michael@0 379 PLARGE_INTEGER aOffset,
michael@0 380 PULONG aKey)
michael@0 381 {
michael@0 382 // Report IO
michael@0 383 WinIOAutoObservation timer(IOInterposeObserver::OpWrite, aFileHandle,
michael@0 384 aOffset);
michael@0 385
michael@0 386 // Something is badly wrong if this function is undefined
michael@0 387 MOZ_ASSERT(gOriginalNtWriteFileGather);
michael@0 388
michael@0 389 // Execute original function
michael@0 390 return gOriginalNtWriteFileGather(
michael@0 391 aFileHandle,
michael@0 392 aEvent,
michael@0 393 aApc,
michael@0 394 aApcCtx,
michael@0 395 aIoStatus,
michael@0 396 aSegments,
michael@0 397 aLength,
michael@0 398 aOffset,
michael@0 399 aKey
michael@0 400 );
michael@0 401 }
michael@0 402
michael@0 403 static NTSTATUS NTAPI InterposedNtFlushBuffersFile(
michael@0 404 HANDLE aFileHandle,
michael@0 405 PIO_STATUS_BLOCK aIoStatusBlock)
michael@0 406 {
michael@0 407 // Report IO
michael@0 408 WinIOAutoObservation timer(IOInterposeObserver::OpFSync, aFileHandle,
michael@0 409 nullptr);
michael@0 410
michael@0 411 // Something is badly wrong if this function is undefined
michael@0 412 MOZ_ASSERT(gOriginalNtFlushBuffersFile);
michael@0 413
michael@0 414 // Execute original function
michael@0 415 return gOriginalNtFlushBuffersFile(
michael@0 416 aFileHandle,
michael@0 417 aIoStatusBlock
michael@0 418 );
michael@0 419 }
michael@0 420
michael@0 421 static NTSTATUS NTAPI InterposedNtQueryFullAttributesFile(
michael@0 422 POBJECT_ATTRIBUTES aObjectAttributes,
michael@0 423 PFILE_NETWORK_OPEN_INFORMATION aFileInformation)
michael@0 424 {
michael@0 425 // Report IO
michael@0 426 const wchar_t* buf = aObjectAttributes ?
michael@0 427 aObjectAttributes->ObjectName->Buffer :
michael@0 428 L"";
michael@0 429 uint32_t len = aObjectAttributes ?
michael@0 430 aObjectAttributes->ObjectName->Length / sizeof(WCHAR) :
michael@0 431 0;
michael@0 432 nsDependentSubstring filename(buf, len);
michael@0 433 WinIOAutoObservation timer(IOInterposeObserver::OpStat, filename);
michael@0 434
michael@0 435 // Something is badly wrong if this function is undefined
michael@0 436 MOZ_ASSERT(gOriginalNtQueryFullAttributesFile);
michael@0 437
michael@0 438 // Execute original function
michael@0 439 return gOriginalNtQueryFullAttributesFile(
michael@0 440 aObjectAttributes,
michael@0 441 aFileInformation
michael@0 442 );
michael@0 443 }
michael@0 444
michael@0 445 } // anonymous namespace
michael@0 446
michael@0 447 /******************************** IO Poisoning ********************************/
michael@0 448
michael@0 449 // Windows DLL interceptor
michael@0 450 static WindowsDllInterceptor sNtDllInterceptor;
michael@0 451
michael@0 452 namespace mozilla {
michael@0 453
michael@0 454 void InitPoisonIOInterposer() {
michael@0 455 // Don't poison twice... as this function may only be invoked on the main
michael@0 456 // thread when no other threads are running, it safe to allow multiple calls
michael@0 457 // to InitPoisonIOInterposer() without complaining (ie. failing assertions).
michael@0 458 if (sIOPoisoned) {
michael@0 459 return;
michael@0 460 }
michael@0 461 sIOPoisoned = true;
michael@0 462
michael@0 463 // Stdout and Stderr are OK.
michael@0 464 MozillaRegisterDebugFD(1);
michael@0 465 MozillaRegisterDebugFD(2);
michael@0 466
michael@0 467 // Initialize dll interceptor and add hooks
michael@0 468 sNtDllInterceptor.Init("ntdll.dll");
michael@0 469 sNtDllInterceptor.AddHook(
michael@0 470 "NtCreateFile",
michael@0 471 reinterpret_cast<intptr_t>(InterposedNtCreateFile),
michael@0 472 reinterpret_cast<void**>(&gOriginalNtCreateFile)
michael@0 473 );
michael@0 474 sNtDllInterceptor.AddHook(
michael@0 475 "NtReadFile",
michael@0 476 reinterpret_cast<intptr_t>(InterposedNtReadFile),
michael@0 477 reinterpret_cast<void**>(&gOriginalNtReadFile)
michael@0 478 );
michael@0 479 sNtDllInterceptor.AddHook(
michael@0 480 "NtReadFileScatter",
michael@0 481 reinterpret_cast<intptr_t>(InterposedNtReadFileScatter),
michael@0 482 reinterpret_cast<void**>(&gOriginalNtReadFileScatter)
michael@0 483 );
michael@0 484 sNtDllInterceptor.AddHook(
michael@0 485 "NtWriteFile",
michael@0 486 reinterpret_cast<intptr_t>(InterposedNtWriteFile),
michael@0 487 reinterpret_cast<void**>(&gOriginalNtWriteFile)
michael@0 488 );
michael@0 489 sNtDllInterceptor.AddHook(
michael@0 490 "NtWriteFileGather",
michael@0 491 reinterpret_cast<intptr_t>(InterposedNtWriteFileGather),
michael@0 492 reinterpret_cast<void**>(&gOriginalNtWriteFileGather)
michael@0 493 );
michael@0 494 sNtDllInterceptor.AddHook(
michael@0 495 "NtFlushBuffersFile",
michael@0 496 reinterpret_cast<intptr_t>(InterposedNtFlushBuffersFile),
michael@0 497 reinterpret_cast<void**>(&gOriginalNtFlushBuffersFile)
michael@0 498 );
michael@0 499 sNtDllInterceptor.AddHook(
michael@0 500 "NtQueryFullAttributesFile",
michael@0 501 reinterpret_cast<intptr_t>(InterposedNtQueryFullAttributesFile),
michael@0 502 reinterpret_cast<void**>(&gOriginalNtQueryFullAttributesFile)
michael@0 503 );
michael@0 504 }
michael@0 505
michael@0 506 void ClearPoisonIOInterposer() {
michael@0 507 MOZ_ASSERT(false);
michael@0 508 if (sIOPoisoned) {
michael@0 509 // Destroy the DLL interceptor
michael@0 510 sIOPoisoned = false;
michael@0 511 sNtDllInterceptor = WindowsDllInterceptor();
michael@0 512 }
michael@0 513 }
michael@0 514
michael@0 515 } // namespace mozilla

mercurial