diff options
Diffstat (limited to 'xpcom/tests/windows')
-rw-r--r-- | xpcom/tests/windows/TestCOM.cpp | 158 | ||||
-rw-r--r-- | xpcom/tests/windows/TestHelloXPLoop.cpp | 144 | ||||
-rw-r--r-- | xpcom/tests/windows/TestNTFSPermissions.cpp | 286 | ||||
-rw-r--r-- | xpcom/tests/windows/TestNtPathToDosPath.cpp | 193 | ||||
-rw-r--r-- | xpcom/tests/windows/TestWinFileAttribs.cpp | 173 | ||||
-rw-r--r-- | xpcom/tests/windows/moz.build | 16 |
6 files changed, 970 insertions, 0 deletions
diff --git a/xpcom/tests/windows/TestCOM.cpp b/xpcom/tests/windows/TestCOM.cpp new file mode 100644 index 000000000..9f0b9854c --- /dev/null +++ b/xpcom/tests/windows/TestCOM.cpp @@ -0,0 +1,158 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <windows.h> +#include <unknwn.h> +#include <stdio.h> +#include "nsISupports.h" +#include "nsIFactory.h" + +// unknwn.h is needed to build with WIN32_LEAN_AND_MEAN +#include <unknwn.h> + +#include "gtest/gtest.h" + +// {5846BA30-B856-11d1-A98A-00805F8A7AC4} +#define NS_ITEST_COM_IID \ +{ 0x5846ba30, 0xb856, 0x11d1, \ + { 0xa9, 0x8a, 0x0, 0x80, 0x5f, 0x8a, 0x7a, 0xc4 } } + +class nsITestCom: public nsISupports +{ +public: + NS_DECLARE_STATIC_IID_ACCESSOR(NS_ITEST_COM_IID) + NS_IMETHOD Test() = 0; +}; + +NS_DEFINE_STATIC_IID_ACCESSOR(nsITestCom, NS_ITEST_COM_IID) + +/* + * nsTestCom + */ + +class nsTestCom final : public nsITestCom { + NS_DECL_ISUPPORTS + +public: + nsTestCom() { + } + + NS_IMETHOD Test() { + return NS_OK; + } + + static int sDestructions; + +private: + ~nsTestCom() { + sDestructions++; + } +}; + +int nsTestCom::sDestructions; + +NS_IMPL_QUERY_INTERFACE(nsTestCom, nsITestCom) + +MozExternalRefCountType nsTestCom::AddRef() +{ + nsrefcnt res = ++mRefCnt; + NS_LOG_ADDREF(this, mRefCnt, "nsTestCom", sizeof(*this)); + return res; +} + +MozExternalRefCountType nsTestCom::Release() +{ + nsrefcnt res = --mRefCnt; + NS_LOG_RELEASE(this, mRefCnt, "nsTestCom"); + if (res == 0) { + delete this; + } + return res; +} + +class nsTestComFactory final : public nsIFactory { + ~nsTestComFactory() { sDestructions++; } + NS_DECL_ISUPPORTS +public: + nsTestComFactory() { + } + + NS_IMETHOD CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult); + + NS_IMETHOD LockFactory(bool aLock) { + return NS_OK; + } + + static int sDestructions; +}; + +int nsTestComFactory::sDestructions; + +NS_IMPL_ISUPPORTS(nsTestComFactory, nsIFactory) + +nsresult nsTestComFactory::CreateInstance(nsISupports *aOuter, + const nsIID &aIID, + void **aResult) +{ + if (aOuter != nullptr) { + return NS_ERROR_NO_AGGREGATION; + } + + nsTestCom *t = new nsTestCom(); + + if (t == nullptr) { + return NS_ERROR_OUT_OF_MEMORY; + } + + NS_ADDREF(t); + nsresult res = t->QueryInterface(aIID, aResult); + NS_RELEASE(t); + + return res; +} + +TEST(TestCOM, WindowsInterop) +{ + nsTestComFactory *inst = new nsTestComFactory(); + + // Test we can QI nsIFactory to an IClassFactory. + IClassFactory *iFactory = nullptr; + nsresult rv = inst->QueryInterface(NS_GET_IID(nsIFactory), + (void **) &iFactory); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + ASSERT_TRUE(iFactory); + + // Test we can CreateInstance with an IUnknown. + IUnknown *iUnknown = nullptr; + + HRESULT hr = iFactory->LockServer(TRUE); + ASSERT_TRUE(SUCCEEDED(hr)); + hr = iFactory->CreateInstance(nullptr, IID_IUnknown, (void **) &iUnknown); + ASSERT_TRUE(SUCCEEDED(hr)); + ASSERT_TRUE(iUnknown); + hr = iFactory->LockServer(FALSE); + ASSERT_TRUE(SUCCEEDED(hr)); + + // Test we can QI an IUnknown to nsITestCom. + nsITestCom *iTestCom = nullptr; + GUID testGUID = NS_ITEST_COM_IID; + hr = iUnknown->QueryInterface(testGUID, + (void **) &iTestCom); + ASSERT_TRUE(SUCCEEDED(hr)); + ASSERT_TRUE(iTestCom); + + // Make sure we can call our test function (and the pointer is valid). + rv = iTestCom->Test(); + ASSERT_TRUE(NS_SUCCEEDED(rv)); + + iUnknown->Release(); + iTestCom->Release(); + iFactory->Release(); + + ASSERT_EQ(nsTestComFactory::sDestructions, 1); + ASSERT_EQ(nsTestCom::sDestructions, 1); +} diff --git a/xpcom/tests/windows/TestHelloXPLoop.cpp b/xpcom/tests/windows/TestHelloXPLoop.cpp new file mode 100644 index 000000000..ffb4442e0 --- /dev/null +++ b/xpcom/tests/windows/TestHelloXPLoop.cpp @@ -0,0 +1,144 @@ +/* -*- Mode: C++; tab-width: 4; indent-tabs-mode: nil; c-basic-offset: 2 -*- + * + * This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include "nsIServiceManager.h" +#include "nsCOMPtr.h" +#include "nsCNativeApp.h" +#include "nsIEventLoop.h" +#include <windows.h> + +static NS_DEFINE_CID(kNativeAppCID, NS_NATIVE_APP_CID); + +LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam); + +void ErrorBox(LPSTR text) +{ + MessageBox(nullptr, text, "XP Event Loop", MB_OK | MB_ICONSTOP); +} + +void InfoBox(LPSTR text) +{ + MessageBox(nullptr, text, "XP Event Loop", MB_OK | MB_ICONINFORMATION); +} + +int WINAPI WinMain(HINSTANCE inst, + HINSTANCE prevInstance, + LPSTR lpszCmdLine, + int nShowCmd) +{ + char* lpszAppName = "HelloWorld"; + HWND wnd; + WNDCLASSEX wndclass; + int retCode; + + { // Needed to scope all nsCOMPtr within XPCOM Init and Shutdown + nsresult rv; + nsCOMPtr<nsIServiceManager> servMan; + rv = NS_InitXPCOM2(getter_AddRefs(servMan), nullptr, nullptr); + if(NS_FAILED(rv)) + { + ErrorBox("Failed to initialize xpcom."); + return -1; + } + + nsCOMPtr<nsIComponentRegistrar> registrar = do_QueryInterface(servMan); + NS_ASSERTION(registrar, "Null nsIComponentRegistrar"); + registrar->AutoRegister(nullptr); + + nsCOMPtr<nsINativeApp> nativeAppService(do_GetService(kNativeAppCID, &rv)); + + if(NS_FAILED(rv)) + { + ErrorBox("Failed to get nativeAppService"); + return -1; + } + wndclass.cbSize = sizeof(wndclass); + wndclass.style = CS_HREDRAW | CS_VREDRAW; + wndclass.lpfnWndProc = WndProc; + wndclass.cbClsExtra = 0; + wndclass.cbWndExtra = 0; + wndclass.hInstance = inst; + wndclass.hIcon = LoadIcon(nullptr, IDI_APPLICATION); + wndclass.hCursor = LoadCursor(nullptr, IDC_ARROW); + wndclass.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wndclass.lpszMenuName = nullptr; + wndclass.lpszClassName = lpszAppName; + wndclass.hIconSm = LoadIcon(nullptr, IDI_APPLICATION); + + RegisterClassEx(&wndclass) ; + + wnd = CreateWindow(lpszAppName, "The Hello World", + WS_OVERLAPPEDWINDOW, + CW_USEDEFAULT, CW_USEDEFAULT, + CW_USEDEFAULT, CW_USEDEFAULT, + nullptr, nullptr, inst, nullptr); + + ShowWindow(wnd, nShowCmd); + UpdateWindow(wnd); + + nsCOMPtr<nsIEventLoop> eventLoop; + + if(NS_FAILED(nativeAppService->CreateEventLoop(L"_MainLoop", + nsEventLoopTypes::MainAppLoop, getter_AddRefs(eventLoop)))) + { + ErrorBox("Failed to create event Loop"); + return 0; + } + + eventLoop->Run(nullptr, nullptr, nullptr, &retCode); + eventLoop = nullptr; // Clear out before Shutting down XPCOM + + InfoBox("Hello World app is out of loop"); + } + NS_ShutdownXPCOM(nullptr); + InfoBox("Hello World app is exiting"); + return retCode; +} + +LRESULT CALLBACK WndProc(HWND wnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + HDC hdc; + PAINTSTRUCT ps; + RECT rect; + + switch(msg) + { + case WM_PAINT: + hdc = BeginPaint(wnd, &ps); + + GetClientRect(wnd, &rect); + + DrawText(hdc, "Hello, XP Event Loop!", -1, &rect, + DT_SINGLELINE | DT_CENTER | DT_VCENTER); + + EndPaint(wnd, &ps); + return 0; + + case WM_DESTROY: + { + nsresult rv; + nsCOMPtr<nsINativeApp> nativeAppService = + do_GetService(kNativeAppCID, &rv); + if(NS_FAILED(rv)) + { + ErrorBox("Could not get NativeAppService"); + return 0; + } + nsCOMPtr<nsIEventLoop> eventLoop; + + if(NS_FAILED(nativeAppService->FindEventLoop(L"_MainLoop", + getter_AddRefs(eventLoop)))) + { + ErrorBox("Failed to find event Loop"); + return 0; + } + eventLoop->Exit(0); + } + return 0; + } + + return DefWindowProc(wnd, msg, wParam, lParam); +} diff --git a/xpcom/tests/windows/TestNTFSPermissions.cpp b/xpcom/tests/windows/TestNTFSPermissions.cpp new file mode 100644 index 000000000..062a9e650 --- /dev/null +++ b/xpcom/tests/windows/TestNTFSPermissions.cpp @@ -0,0 +1,286 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 4 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test for NTFS File Permissions being correctly changed to match the new + * directory upon moving a file. (Bug 224692.) + */ + +#include "../TestHarness.h" +#include "nsEmbedString.h" +#include "nsIFile.h" +#include <windows.h> +#include <aclapi.h> + +#define BUFFSIZE 512 + + + +nsresult TestPermissions() +{ + + nsresult rv; // Return value + + // File variables + HANDLE tempFileHandle; + nsCOMPtr<nsIFile> tempFile; + nsCOMPtr<nsIFile> tempDirectory1; + nsCOMPtr<nsIFile> tempDirectory2; + WCHAR filePath[MAX_PATH]; + WCHAR dir1Path[MAX_PATH]; + WCHAR dir2Path[MAX_PATH]; + + // Security variables + DWORD result; + PSID everyoneSID = nullptr, adminSID = nullptr; + PACL dirACL = nullptr, fileACL = nullptr; + PSECURITY_DESCRIPTOR dirSD = nullptr, fileSD = nullptr; + EXPLICIT_ACCESS ea[2]; + SID_IDENTIFIER_AUTHORITY SIDAuthWorld = + SECURITY_WORLD_SID_AUTHORITY; + SID_IDENTIFIER_AUTHORITY SIDAuthNT = SECURITY_NT_AUTHORITY; + SECURITY_ATTRIBUTES sa; + TRUSTEE everyoneTrustee; + ACCESS_MASK everyoneRights; + + // Create a well-known SID for the Everyone group. + if(!AllocateAndInitializeSid(&SIDAuthWorld, 1, + SECURITY_WORLD_RID, + 0, 0, 0, 0, 0, 0, 0, + &everyoneSID)) + { + fail("NTFS Permissions: AllocateAndInitializeSid Error"); + return NS_ERROR_FAILURE; + } + + // Create a SID for the Administrators group. + if(! AllocateAndInitializeSid(&SIDAuthNT, 2, + SECURITY_BUILTIN_DOMAIN_RID, + DOMAIN_ALIAS_RID_ADMINS, + 0, 0, 0, 0, 0, 0, + &adminSID)) + { + fail("NTFS Permissions: AllocateAndInitializeSid Error"); + return NS_ERROR_FAILURE; + } + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow Everyone read access to the directory. + ZeroMemory(&ea, 2 * sizeof(EXPLICIT_ACCESS)); + ea[0].grfAccessPermissions = GENERIC_READ; + ea[0].grfAccessMode = SET_ACCESS; + ea[0].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[0].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[0].Trustee.TrusteeType = TRUSTEE_IS_WELL_KNOWN_GROUP; + ea[0].Trustee.ptstrName = (LPTSTR) everyoneSID; + + // Initialize an EXPLICIT_ACCESS structure for an ACE. + // The ACE will allow the Administrators group full access + ea[1].grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; + ea[1].grfAccessMode = SET_ACCESS; + ea[1].grfInheritance= SUB_CONTAINERS_AND_OBJECTS_INHERIT; + ea[1].Trustee.TrusteeForm = TRUSTEE_IS_SID; + ea[1].Trustee.TrusteeType = TRUSTEE_IS_GROUP; + ea[1].Trustee.ptstrName = (LPTSTR) adminSID; + + // Create a new ACL that contains the new ACEs. + result = SetEntriesInAcl(2, ea, nullptr, &dirACL); + if (ERROR_SUCCESS != result) + { + fail("NTFS Permissions: SetEntriesInAcl Error"); + return NS_ERROR_FAILURE; + } + + // Initialize a security descriptor. + dirSD = (PSECURITY_DESCRIPTOR) LocalAlloc(LPTR, + SECURITY_DESCRIPTOR_MIN_LENGTH); + if (nullptr == dirSD) + { + fail("NTFS Permissions: LocalAlloc Error"); + return NS_ERROR_FAILURE; + } + + if (!InitializeSecurityDescriptor(dirSD, + SECURITY_DESCRIPTOR_REVISION)) + { + fail("NTFS Permissions: InitializeSecurityDescriptor Error"); + return NS_ERROR_FAILURE; + } + + // Add the ACL to the security descriptor. + if (!SetSecurityDescriptorDacl(dirSD, true, dirACL, false)) + { + fail("NTFS Permissions: SetSecurityDescriptorDacl Error"); + return NS_ERROR_FAILURE; + } + + // Initialize a security attributes structure. + sa.nLength = sizeof (SECURITY_ATTRIBUTES); + sa.lpSecurityDescriptor = dirSD; + sa.bInheritHandle = false; + + // Create and open first temporary directory + if(!CreateDirectoryW(L".\\NTFSPERMTEMP1", &sa)) + { + fail("NTFS Permissions: Creating Temporary Directory"); + return NS_ERROR_FAILURE; + } + + GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP1", MAX_PATH, dir1Path, + nullptr); + + rv = NS_NewLocalFile(nsEmbedString(dir1Path), false, + getter_AddRefs(tempDirectory1)); + if (NS_FAILED(rv)) + { + fail("NTFS Permissions: Opening Temporary Directory 1"); + return rv; + } + + + // Create and open temporary file + tempFileHandle = CreateFileW(L".\\NTFSPERMTEMP1\\NTFSPerm.tmp", + GENERIC_READ | GENERIC_WRITE, + 0, + nullptr, //default security + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, + nullptr); + + if(tempFileHandle == INVALID_HANDLE_VALUE) + { + fail("NTFS Permissions: Creating Temporary File"); + return NS_ERROR_FAILURE; + } + + CloseHandle(tempFileHandle); + + GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP1\\NTFSPerm.tmp", + MAX_PATH, filePath, nullptr); + + rv = NS_NewLocalFile(nsEmbedString(filePath), false, + getter_AddRefs(tempFile)); + if (NS_FAILED(rv)) + { + fail("NTFS Permissions: Opening Temporary File"); + return rv; + } + + // Update Everyone Explict_Acess to full access. + ea[0].grfAccessPermissions = GENERIC_ALL | STANDARD_RIGHTS_ALL; + + // Update the ACL to contain the new ACEs. + result = SetEntriesInAcl(2, ea, nullptr, &dirACL); + if (ERROR_SUCCESS != result) + { + fail("NTFS Permissions: SetEntriesInAcl 2 Error"); + return NS_ERROR_FAILURE; + } + + // Add the new ACL to the security descriptor. + if (!SetSecurityDescriptorDacl(dirSD, true, dirACL, false)) + { + fail("NTFS Permissions: SetSecurityDescriptorDacl 2 Error"); + return NS_ERROR_FAILURE; + } + + // Create and open second temporary directory + if(!CreateDirectoryW(L".\\NTFSPERMTEMP2", &sa)) + { + fail("NTFS Permissions: Creating Temporary Directory 2"); + return NS_ERROR_FAILURE; + } + + GetFullPathNameW((LPCWSTR)L".\\NTFSPERMTEMP2", MAX_PATH, dir2Path, + nullptr); + + rv = NS_NewLocalFile(nsEmbedString(dir2Path), false, + getter_AddRefs(tempDirectory2)); + if (NS_FAILED(rv)) + { + fail("NTFS Permissions: Opening Temporary Directory 2"); + return rv; + } + + // Move the file. + rv = tempFile->MoveTo(tempDirectory2, EmptyString()); + + if (NS_FAILED(rv)) + { + fail("NTFS Permissions: Moving"); + return rv; + } + + // Access the ACL of the file + result = GetNamedSecurityInfoW(L".\\NTFSPERMTEMP2\\NTFSPerm.tmp", + SE_FILE_OBJECT, + DACL_SECURITY_INFORMATION | + UNPROTECTED_DACL_SECURITY_INFORMATION, + nullptr, nullptr, &fileACL, nullptr, + &fileSD); + if (ERROR_SUCCESS != result) + { + fail("NTFS Permissions: GetNamedSecurityDescriptor Error"); + return NS_ERROR_FAILURE; + } + + // Build a trustee representing "Everyone" + BuildTrusteeWithSid(&everyoneTrustee, everyoneSID); + + // Get Everyone's effective rights. + result = GetEffectiveRightsFromAcl(fileACL, &everyoneTrustee, + &everyoneRights); + if (ERROR_SUCCESS != result) + { + fail("NTFS Permissions: GetEffectiveRightsFromAcl Error"); + return NS_ERROR_FAILURE; + } + + // Check for delete access, which we won't have unless permissions have + // updated + if((everyoneRights & DELETE) == (DELETE)) + { + passed("NTFS Permissions Test"); + rv = NS_OK; + } + else + { + fail("NTFS Permissions: Access check."); + rv = NS_ERROR_FAILURE; + } + + // Cleanup + if (everyoneSID) + FreeSid(everyoneSID); + if (adminSID) + FreeSid(adminSID); + if (dirACL) + LocalFree(dirACL); + if (dirSD) + LocalFree(dirSD); + if(fileACL) + LocalFree(fileACL); + + tempDirectory1->Remove(true); + tempDirectory2->Remove(true); + + return rv; +} + +int main(int argc, char** argv) +{ + ScopedXPCOM xpcom("NTFSPermissionsTests"); // name for tests being run + if (xpcom.failed()) + return 1; + + int rv = 0; + + if(NS_FAILED(TestPermissions())) + rv = 1; + + return rv; + +} + diff --git a/xpcom/tests/windows/TestNtPathToDosPath.cpp b/xpcom/tests/windows/TestNtPathToDosPath.cpp new file mode 100644 index 000000000..b826d4f20 --- /dev/null +++ b/xpcom/tests/windows/TestNtPathToDosPath.cpp @@ -0,0 +1,193 @@ +/* -*- Mode: C++; tab-width: 8; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* vim: set ts=8 sts=2 et sw=2 tw=80: */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +#include <windows.h> +#include <winnetwk.h> + +#include "mozilla/FileUtilsWin.h" +#include "mozilla/DebugOnly.h" +#include "nsCRTGlue.h" + +#include "gtest/gtest.h" + +class DriveMapping +{ +public: + DriveMapping(const nsAString& aRemoteUNCPath); + ~DriveMapping(); + + bool + Init(); + bool + ChangeDriveLetter(); + wchar_t + GetDriveLetter() { return mDriveLetter; } + +private: + bool + DoMapping(); + void + Disconnect(wchar_t aDriveLetter); + + wchar_t mDriveLetter; + nsString mRemoteUNCPath; +}; + +DriveMapping::DriveMapping(const nsAString& aRemoteUNCPath) + : mDriveLetter(0) + , mRemoteUNCPath(aRemoteUNCPath) +{ +} + +bool +DriveMapping::Init() +{ + if (mDriveLetter) { + return false; + } + return DoMapping(); +} + +bool +DriveMapping::DoMapping() +{ + wchar_t drvTemplate[] = L" :"; + NETRESOURCEW netRes = {0}; + netRes.dwType = RESOURCETYPE_DISK; + netRes.lpLocalName = drvTemplate; + netRes.lpRemoteName = reinterpret_cast<wchar_t*>(mRemoteUNCPath.BeginWriting()); + wchar_t driveLetter = L'D'; + DWORD result = NO_ERROR; + do { + drvTemplate[0] = driveLetter; + result = WNetAddConnection2W(&netRes, nullptr, nullptr, CONNECT_TEMPORARY); + } while (result == ERROR_ALREADY_ASSIGNED && ++driveLetter <= L'Z'); + if (result != NO_ERROR) { + return false; + } + mDriveLetter = driveLetter; + return true; +} + +bool +DriveMapping::ChangeDriveLetter() +{ + wchar_t prevDriveLetter = mDriveLetter; + bool result = DoMapping(); + MOZ_RELEASE_ASSERT(mDriveLetter != prevDriveLetter); + if (result && prevDriveLetter) { + Disconnect(prevDriveLetter); + } + return result; +} + +void +DriveMapping::Disconnect(wchar_t aDriveLetter) +{ + wchar_t drvTemplate[] = {aDriveLetter, L':', L'\0'}; + DWORD result = WNetCancelConnection2W(drvTemplate, 0, TRUE); + MOZ_RELEASE_ASSERT(result == NO_ERROR); +} + +DriveMapping::~DriveMapping() +{ + if (mDriveLetter) { + Disconnect(mDriveLetter); + } +} + +bool +DriveToNtPath(const wchar_t aDriveLetter, nsAString& aNtPath) +{ + const wchar_t drvTpl[] = {aDriveLetter, L':', L'\0'}; + aNtPath.SetLength(MAX_PATH); + DWORD pathLen; + while (true) { + pathLen = QueryDosDeviceW(drvTpl, reinterpret_cast<wchar_t*>(aNtPath.BeginWriting()), aNtPath.Length()); + if (pathLen || GetLastError() != ERROR_INSUFFICIENT_BUFFER) { + break; + } + aNtPath.SetLength(aNtPath.Length() * 2); + } + if (!pathLen) { + return false; + } + // aNtPath contains embedded NULLs, so we need to figure out the real length + // via wcslen. + aNtPath.SetLength(NS_strlen(aNtPath.BeginReading())); + return true; +} + +bool +TestNtPathToDosPath(const wchar_t* aNtPath, + const wchar_t* aExpectedDosPath) +{ + nsAutoString output; + bool result = mozilla::NtPathToDosPath(nsDependentString(aNtPath), output); + return result && output == reinterpret_cast<const nsAString::char_type *>(aExpectedDosPath); +} + +TEST(NtPathToDosPath, Tests) +{ + nsAutoString cDrive; + ASSERT_TRUE(DriveToNtPath(L'C', cDrive)); + + // empty string + EXPECT_TRUE(TestNtPathToDosPath(L"", L"")); + + // non-existent device, must fail + EXPECT_FALSE(TestNtPathToDosPath(L"\\Device\\ThisDeviceDoesNotExist\\Foo", nullptr)); + + // base case + nsAutoString testPath(cDrive); + testPath.Append(L"\\Program Files"); + EXPECT_TRUE(TestNtPathToDosPath(testPath.get(), L"C:\\Program Files")); + + // short filename + nsAutoString ntShortName(cDrive); + ntShortName.Append(L"\\progra~1"); + EXPECT_TRUE(TestNtPathToDosPath(ntShortName.get(), L"C:\\Program Files")); + + // drive letters as symbolic links (NtCreateFile uses these) + EXPECT_TRUE(TestNtPathToDosPath(L"\\??\\C:\\Foo", L"C:\\Foo")); + + // other symbolic links (should fail) + EXPECT_FALSE(TestNtPathToDosPath(L"\\??\\MountPointManager", nullptr)); + + // socket (should fail) + EXPECT_FALSE(TestNtPathToDosPath(L"\\Device\\Afd\\Endpoint", nullptr)); + + // UNC path (using MUP) + EXPECT_TRUE(TestNtPathToDosPath(L"\\Device\\Mup\\127.0.0.1\\C$", + L"\\\\127.0.0.1\\C$")); + + // UNC path (using LanmanRedirector) + EXPECT_TRUE(TestNtPathToDosPath(L"\\Device\\LanmanRedirector\\127.0.0.1\\C$", + L"\\\\127.0.0.1\\C$")); + + DriveMapping drvMapping(NS_LITERAL_STRING("\\\\127.0.0.1\\C$")); + // Only run these tests if we were able to map; some machines don't have perms + if (drvMapping.Init()) { + wchar_t expected[] = L" :\\"; + expected[0] = drvMapping.GetDriveLetter(); + nsAutoString networkPath; + ASSERT_TRUE(DriveToNtPath(drvMapping.GetDriveLetter(), networkPath)); + + networkPath += u"\\"; + EXPECT_TRUE(TestNtPathToDosPath(networkPath.get(), expected)); + + // NtPathToDosPath must correctly handle paths whose drive letter mapping has + // changed. We need to test this because the APIs called by NtPathToDosPath + // return different info if this has happened. + ASSERT_TRUE(drvMapping.ChangeDriveLetter()); + + expected[0] = drvMapping.GetDriveLetter(); + ASSERT_TRUE(DriveToNtPath(drvMapping.GetDriveLetter(), networkPath)); + + networkPath += u"\\"; + EXPECT_TRUE(TestNtPathToDosPath(networkPath.get(), expected)); + } +} diff --git a/xpcom/tests/windows/TestWinFileAttribs.cpp b/xpcom/tests/windows/TestWinFileAttribs.cpp new file mode 100644 index 000000000..56fbcbdea --- /dev/null +++ b/xpcom/tests/windows/TestWinFileAttribs.cpp @@ -0,0 +1,173 @@ +/* -*- Mode: C++; tab-width: 2; indent-tabs-mode: nil; c-basic-offset: 2 -*- */ +/* This Source Code Form is subject to the terms of the Mozilla Public + * License, v. 2.0. If a copy of the MPL was not distributed with this + * file, You can obtain one at http://mozilla.org/MPL/2.0/. */ + +/* + * Test: + */ + +#include "../TestHarness.h" +#include "nsEmbedString.h" +#include "nsILocalFileWin.h" +#include <windows.h> + +#define BUFFSIZE 512 + +nsresult TestWinAttribs() +{ + + nsresult rv; + + // File variables + HANDLE hIndexed; + nsCOMPtr<nsIFile> localFile; + WCHAR filePath[MAX_PATH]; + + // Create and open temporary file + hIndexed = CreateFileW(L".\\indexbit.txt", + GENERIC_READ | GENERIC_WRITE, + 0, + nullptr, + CREATE_ALWAYS, + FILE_ATTRIBUTE_NORMAL, //FILE_ATTRIBUTE_NOT_CONTENT_INDEXED, not supported by cf + nullptr); + + if(hIndexed == INVALID_HANDLE_VALUE) + { + fail("Test Win Attribs: Creating Test File"); + return NS_ERROR_FAILURE; + } + + CloseHandle(hIndexed); + + GetFullPathNameW((LPCWSTR)L".\\indexbit.txt", + MAX_PATH, filePath, nullptr); + + //wprintf(filePath); + //wprintf(L"\n"); + + rv = NS_NewLocalFile(nsEmbedString(filePath), false, + getter_AddRefs(localFile)); + if (NS_FAILED(rv)) + { + fail("Test Win Attribs: Opening Test File"); + DeleteFileW(filePath); + return rv; + } + + nsCOMPtr<nsILocalFileWin> localFileWin(do_QueryInterface(localFile)); + + DWORD dwAttrs = GetFileAttributesW(filePath); + if (dwAttrs == INVALID_FILE_ATTRIBUTES) + { + fail("Test Win Attribs: GetFileAttributesW - couldn't find our temp file."); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + dwAttrs |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; + SetFileAttributesW(filePath, dwAttrs); + + uint32_t attribs = 0; + rv = localFileWin->GetFileAttributesWin(&attribs); + + if (NS_FAILED(rv)) + { + fail("Test Win Attribs: GetFileAttributesWin failed to GET attributes. (1)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + if (attribs & nsILocalFileWin::WFA_SEARCH_INDEXED) + { + fail("Test Win Attribs: GetFileAttributesWin attributed did not match. (2)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + dwAttrs &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; + SetFileAttributesW(filePath, dwAttrs); + + rv = localFileWin->GetFileAttributesWin(&attribs); + + if (NS_FAILED(rv)) + { + fail("Test Win Attribs: GetFileAttributesWin failed to GET attributes. (3)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + if (!(attribs & nsILocalFileWin::WFA_SEARCH_INDEXED)) + { + fail("Test Win Attribs: GetFileAttributesWin attributed did not match. (4)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + dwAttrs &= ~FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; + SetFileAttributesW(filePath, dwAttrs); + + attribs = nsILocalFileWin::WFA_SEARCH_INDEXED; + rv = localFileWin->SetFileAttributesWin(attribs); + + dwAttrs = GetFileAttributesW(filePath); + + if (NS_FAILED(rv)) + { + fail("Test Win Attribs: GetFileAttributesWin failed to SET attributes. (5)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + if (dwAttrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED) + { + fail("Test Win Attribs: SetFileAttributesWin attributed did not match. (6)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + dwAttrs |= FILE_ATTRIBUTE_NOT_CONTENT_INDEXED; + SetFileAttributesW(filePath, dwAttrs); + + attribs = 0; + rv = localFileWin->SetFileAttributesWin(attribs); + + dwAttrs = GetFileAttributesW(filePath); + + if (NS_FAILED(rv)) + { + fail("Test Win Attribs: GetFileAttributesWin failed to SET attributes. (7)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + if (!(dwAttrs & FILE_ATTRIBUTE_NOT_CONTENT_INDEXED)) + { + fail("Test Win Attribs: SetFileAttributesWin attributed did not match. (8)"); + DeleteFileW(filePath); + return NS_ERROR_FAILURE; + } + + DeleteFileW(filePath); + + passed("Test Win Attribs: passed tests."); + + return NS_OK; +} + +int main(int argc, char** argv) +{ + ScopedXPCOM xpcom("WinFileAttributes"); + if (xpcom.failed()) + return 1; + + int rv = 0; + + if(NS_FAILED(TestWinAttribs())) + rv = 1; + + return rv; + +} + diff --git a/xpcom/tests/windows/moz.build b/xpcom/tests/windows/moz.build new file mode 100644 index 000000000..21b5eb2f7 --- /dev/null +++ b/xpcom/tests/windows/moz.build @@ -0,0 +1,16 @@ +# -*- Mode: python; indent-tabs-mode: nil; tab-width: 40 -*- +# vim: set filetype=python: +# This Source Code Form is subject to the terms of the Mozilla Public +# License, v. 2.0. If a copy of the MPL was not distributed with this +# file, You can obtain one at http://mozilla.org/MPL/2.0/. + +UNIFIED_SOURCES += [ + 'TestCOM.cpp', + 'TestNtPathToDosPath.cpp', +] + +OS_LIBS += [ + 'mpr', +] + +FINAL_LIBRARY = 'xul-gtest' |