diff options
Diffstat (limited to 'cpp/src')
-rw-r--r-- | cpp/src/Glacier2/ClientBlobject.cpp | 65 | ||||
-rw-r--r-- | cpp/src/Glacier2/ClientBlobject.h | 10 | ||||
-rwxr-xr-x | cpp/src/Glacier2/FilterI.cpp | 11 | ||||
-rwxr-xr-x | cpp/src/Glacier2/FilterI.h | 278 | ||||
-rw-r--r-- | cpp/src/Glacier2/ProxyVerifier.cpp | 3 | ||||
-rw-r--r-- | cpp/src/Glacier2/RouterI.cpp | 113 | ||||
-rw-r--r-- | cpp/src/Glacier2/RouterI.h | 6 | ||||
-rw-r--r-- | cpp/src/Glacier2/SessionRouterI.cpp | 23 | ||||
-rwxr-xr-x | cpp/src/Glacier2/glacier2router.dsp | 8 | ||||
-rw-r--r-- | cpp/src/Slice/slice.dsp | 5 |
10 files changed, 471 insertions, 51 deletions
diff --git a/cpp/src/Glacier2/ClientBlobject.cpp b/cpp/src/Glacier2/ClientBlobject.cpp index 0f09f1925fd..96cd370ef91 100644 --- a/cpp/src/Glacier2/ClientBlobject.cpp +++ b/cpp/src/Glacier2/ClientBlobject.cpp @@ -15,10 +15,14 @@ using namespace Glacier2; Glacier2::ClientBlobject::ClientBlobject(const CommunicatorPtr& communicator, const RoutingTablePtr& routingTable, - const StringSeq& allowCategories) : + const StringFilterIPtr& categoryFilter, + const StringFilterIPtr& adapterIdFilter, + const IdentityFilterIPtr& objectIdFilter): Glacier2::Blobject(communicator, false), _routingTable(routingTable), - _allowCategories(allowCategories), + _categoryFilter(categoryFilter), + _adapterIdFilter(adapterIdFilter), + _objectIdFilter(objectIdFilter), _rejectTraceLevel(_properties->getPropertyAsInt("Glacier2.Client.Trace.Reject")) { } @@ -32,31 +36,30 @@ Glacier2::ClientBlobject::ice_invoke_async(const Ice::AMD_Array_Object_ice_invok const std::pair<const Byte*, const Byte*>& inParams, const Current& current) { - // - // If there is an _allowCategories set then enforce it. - // - if(!_allowCategories.empty()) + if(!_categoryFilter->match(current.id.category)) { - // - // Note: Some filtering will be relying on regular - // expressions. A quick performance test revealed that on Linux - // using the standard regular expression API to create an - // equivalent mechanism was much slower when there were a large - // number of categories. It would appear that the simple - // mechanism used here is a better choice, at least on Linux. - // - if(!binary_search(_allowCategories.begin(), _allowCategories.end(), current.id.category)) + if(_rejectTraceLevel >= 1) { - if(_rejectTraceLevel >= 1) - { - Trace out(_logger, "Glacier2"); - out << "rejecting request\n"; - out << "identity: " << _communicator->identityToString(current.id); - } - ObjectNotExistException ex(__FILE__, __LINE__); - ex.id = current.id; - throw ex; + Trace out(_logger, "Glacier2"); + out << "rejecting request\n"; + out << "identity: " << _communicator->identityToString(current.id); } + ObjectNotExistException ex(__FILE__, __LINE__); + ex.id = current.id; + throw ex; + } + + if(!_objectIdFilter->match(current.id)) + { + if(_rejectTraceLevel >= 1) + { + Trace out(_logger, "Glacier2"); + out << "rejecting request\n"; + out << "identity: " << _communicator->identityToString(current.id); + } + ObjectNotExistException ex(__FILE__, __LINE__); + ex.id = current.id; + throw ex; } ObjectPrx proxy = _routingTable->get(current.id); @@ -77,5 +80,19 @@ Glacier2::ClientBlobject::ice_invoke_async(const Ice::AMD_Array_Object_ice_invok throw ex; } + string adapterId = proxy->ice_getAdapterId(); + if(!adapterId.empty() && !_adapterIdFilter->match(adapterId)) + { + if(_rejectTraceLevel >= 1) + { + Trace out(_logger, "Glacier2"); + out << "rejecting request\n"; + out << "identity: " << _communicator->identityToString(current.id); + } + ObjectNotExistException ex(__FILE__, __LINE__); + ex.id = current.id; + throw ex; + } + invoke(proxy, amdCB, inParams, current); } diff --git a/cpp/src/Glacier2/ClientBlobject.h b/cpp/src/Glacier2/ClientBlobject.h index 115b1dd08eb..fbac37e2b7d 100644 --- a/cpp/src/Glacier2/ClientBlobject.h +++ b/cpp/src/Glacier2/ClientBlobject.h @@ -12,6 +12,8 @@ #include <Glacier2/RoutingTable.h> #include <Glacier2/Blobject.h> +#include <Glacier2/Session.h> +#include <Glacier2/FilterI.h> namespace Glacier2 { @@ -23,7 +25,8 @@ class ClientBlobject : public Glacier2::Blobject { public: - ClientBlobject(const Ice::CommunicatorPtr&, const RoutingTablePtr&, const Ice::StringSeq&); + ClientBlobject(const Ice::CommunicatorPtr&, const RoutingTablePtr&, const StringFilterIPtr&, + const StringFilterIPtr&, const IdentityFilterIPtr&); virtual ~ClientBlobject(); virtual void ice_invoke_async(const Ice::AMD_Array_Object_ice_invokePtr&, @@ -32,10 +35,11 @@ public: private: const RoutingTablePtr _routingTable; - const std::vector<std::string> _allowCategories; + const StringFilterIPtr _categoryFilter; + const StringFilterIPtr _adapterIdFilter; + const IdentityFilterIPtr _objectIdFilter; const int _rejectTraceLevel; }; - } #endif diff --git a/cpp/src/Glacier2/FilterI.cpp b/cpp/src/Glacier2/FilterI.cpp new file mode 100755 index 00000000000..644c7917e89 --- /dev/null +++ b/cpp/src/Glacier2/FilterI.cpp @@ -0,0 +1,11 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** + +#include <Glacier2/FilterI.h> +#include <list> diff --git a/cpp/src/Glacier2/FilterI.h b/cpp/src/Glacier2/FilterI.h new file mode 100755 index 00000000000..9462db8eb13 --- /dev/null +++ b/cpp/src/Glacier2/FilterI.h @@ -0,0 +1,278 @@ +// ********************************************************************** +// +// Copyright (c) 2003-2006 ZeroC, Inc. All rights reserved. +// +// This copy of Ice is licensed to you under the terms described in the +// ICE_LICENSE file included in this distribution. +// +// ********************************************************************** +#ifndef FILTER_I_H +#define FILTER_I_H + +#include <Ice/Identity.h> +#include <Glacier2/Session.h> + +namespace Glacier2 +{ + +template <class T, class P> +class FilterT : public P, public IceUtil::Monitor<IceUtil::Mutex> +{ +public: + FilterT(const T&, const T&, const bool); + + // + // Slice to C++ mapping. + // + virtual void addAccept(const T&, const Ice::Current&); + virtual void removeAccept(const T&, const Ice::Current&); + + virtual void setAccept(const T&, const Ice::Current&); + virtual T getAccept(const Ice::Current&) const; + + virtual void addReject(const T&, const Ice::Current&); + virtual void removeReject(const T&, const Ice::Current&); + + virtual void setReject(const T&, const Ice::Current&); + virtual T getReject(const Ice::Current&) const; + + virtual bool getAcceptOverride(const Ice::Current&) const; + virtual void setAcceptOverride(bool value, const Ice::Current&); + + // + // Internal functions. + // + bool + match(const T::value_type& candidate) const + { + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + // + // Empty vectors mean no filtering, so all matches will succeed. + // + if(_accept.size() == 0 && _reject.size() == 0) + { + return true; + } + + bool result; + + if(_reject.size() == 0) + { + // + // No reject filters, treat mode as default reject. + // + result = binary_search(_accept.begin(), _accept.end(), candidate); + } + else if(_accept.size() == 0) + { + // + // No accept filters, treat mode as default accept. + // + result = !binary_search(_reject.begin(), _reject.end(), candidate); + } + else + { + // + // We have both accept and reject filters. We need to consider + // the _acceptOverride flag. + // + if(_acceptOverride) + { + result = !binary_search(_reject.begin(), _reject.end(), candidate); + if(!result) + { + result = binary_search(_accept.begin(), _accept.end(), candidate); + } + } + else + { + result = binary_search(_accept.begin(), _accept.end(), candidate); + if(result) + { + result = !binary_search(_reject.begin(), _reject.end(), candidate); + } + + } + } + return result; + } + +private: + + T _accept; + T _reject; + bool _acceptOverride; + + void addImpl(T&, const T&); + void removeImpl(T&, const T&); +}; + +template<class T, class P> +FilterT<T, P>::FilterT(const T& accept, const T& reject, const bool acceptOverride): + _accept(accept), + _reject(reject), + _acceptOverride(acceptOverride) +{ + sort(_accept.begin(), _accept.end()); + _accept.erase(unique(_accept.begin(), _accept.end()), _accept.end()); + sort(_reject.begin(), _reject.end()); + _reject.erase(unique(_reject.begin(), _reject.end()), _reject.end()); +} + +template<class T, class P> void +FilterT<T, P>::addAccept(const T& additions, const Ice::Current&) +{ + addImpl(_accept, additions); +} + +template<class T, class P> void +FilterT<T, P>::removeAccept(const T& deletions, const Ice::Current&) +{ + removeImpl(_accept, deletions); +} + +template<class T, class P> void +FilterT<T, P>::setAccept(const T& filterElements, const Ice::Current&) +{ + T newItems(filterElements); + sort(newItems.begin(), newItems.end()); + newItems.erase(unique(newItems.begin(), newItems.end()), newItems.end()); + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + swap(newItems, _accept); +} + +template<class T, class P> T +FilterT<T, P>::getAccept(const Ice::Current&) const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + return _accept; +} + +template<class T, class P> void +FilterT<T, P>::addReject(const T& additions, const Ice::Current&) +{ + addImpl(_reject, additions); +} + +template<class T, class P> void +FilterT<T, P>::removeReject(const T& deletions, const Ice::Current&) +{ + removeImpl(_reject, deletions); +} + +template<class T, class P> void +FilterT<T, P>::setReject(const T& filterElements, const Ice::Current&) +{ + T newItems(filterElements); + sort(newItems.begin(), newItems.end()); + newItems.erase(unique(newItems.begin(), newItems.end()), newItems.end()); + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + swap(newItems, _reject); +} + +template<class T, class P> T +FilterT<T, P>::getReject(const Ice::Current&) const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + return _reject; +} + +template<class T, class P> bool +FilterT<T, P>::getAcceptOverride(const Ice::Current&) const +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + return _acceptOverride; +} + +template<class T, class P> void +FilterT<T, P>::setAcceptOverride(bool value, const Ice::Current&) +{ + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + _acceptOverride = value; +} + +template<class T, class P> void +FilterT<T, P>::addImpl(T& dest, const T& additions) +{ + // + // Sort the filter elements first, erasing duplicates. Then we can + // simply use the STL merge algorithm to add to our list of filters. + // + T newItems(additions); + sort(newItems.begin(), newItems.end()); + newItems.erase(unique(newItems.begin(), newItems.end()), newItems.end()); + + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + T merged(dest.size() + newItems.size()); + merge(newItems.begin(), newItems.end(), dest.begin(), dest.end(), merged.begin()); + merged.erase(unique(merged.begin(), merged.end()), merged.end()); + swap(dest, merged); +} + +template<class T, class P> void +FilterT<T, P>::removeImpl(T& dest, const T& deletions) +{ + // + // Our removal algorithm depends on the filter elements to be + // removed to be sorted in the same order as our current elements. + // + T toRemove(dest); + sort(toRemove.begin(), toRemove.end()); + toRemove.erase(unique(toRemove.begin(), toRemove.end()), toRemove.end()); + + IceUtil::Monitor<IceUtil::Mutex>::Lock lock(*this); + + // + // Our vectors are both sorted, so if we keep track of our first + // match between the current set and the set of items to be removed, + // we do not need to traverse the whole of the current set each + // time. We also use a list of deletions instead of erasing things + // itemwise. + // + T::const_iterator r = toRemove.begin(); + T::iterator mark = dest.begin(); + list<T::iterator> deleteList; + + while(r != toRemove.end()) + { + T::iterator i = mark; + while(i != dest.end() && r != toRemove.end()) + { + if(*r == *i) + { + // + // We want this list to be in LIFO order because we are + // going to erase things from the tail forward. + // + deleteList.push_front(i); + ++i; + ++r; + mark = i; + } + else + { + ++i; + } + } + if(r == toRemove.end()) + { + break; + } + ++r; + } + + for(list<T::iterator>::const_iterator i = deleteList.begin(); i != deleteList.end(); ++i) + { + dest.erase(*i); + } +} + +typedef FilterT<Ice::IdentitySeq, Glacier2::IdFilter> IdentityFilterI; +typedef IceUtil::Handle< FilterT<Ice::IdentitySeq, Glacier2::IdFilter> > IdentityFilterIPtr; + +typedef FilterT<std::vector<std::string>, Glacier2::StringFilter> StringFilterI; +typedef IceUtil::Handle< FilterT<std::vector<std::string>, Glacier2::StringFilter> > StringFilterIPtr; + +}; + +#endif diff --git a/cpp/src/Glacier2/ProxyVerifier.cpp b/cpp/src/Glacier2/ProxyVerifier.cpp index 05826d81434..b4fc9703fd6 100644 --- a/cpp/src/Glacier2/ProxyVerifier.cpp +++ b/cpp/src/Glacier2/ProxyVerifier.cpp @@ -244,13 +244,12 @@ Glacier2::ProxyVerifier::verify(const ObjectPrx& proxy) } else { - result = match(_acceptRules, proxy); - // // In this context we are default reject, there is no point // of running the reject filters if there is no accept // match. // + result = match(_acceptRules, proxy); if(result) { result = !match(_rejectRules, proxy); diff --git a/cpp/src/Glacier2/RouterI.cpp b/cpp/src/Glacier2/RouterI.cpp index 02ad6186733..d366cfa8afb 100644 --- a/cpp/src/Glacier2/RouterI.cpp +++ b/cpp/src/Glacier2/RouterI.cpp @@ -11,11 +11,29 @@ #include <Glacier2/RouterI.h> #include <Glacier2/Session.h> +#include <Glacier2/FilterI.h> using namespace std; using namespace Ice; using namespace Glacier2; +// +// Parse a space delimited string into a sequence of strings. +// +static void +stringToSeq(const string& str, vector<string>& seq) +{ + string const ws = " \t"; + string::size_type current = str.find_first_not_of(ws, 0); + while(current != string::npos) + { + string::size_type pos = str.find_first_of(ws, current); + string::size_type len = (pos == string::npos) ? string::npos : pos - current; + seq.push_back(str.substr(current, len)); + current = str.find_first_not_of(ws, pos); + } +} + Glacier2::RouterI::RouterI(const ObjectAdapterPtr& clientAdapter, const ObjectAdapterPtr& serverAdapter, const ObjectAdapterPtr& adminAdapter, const ConnectionPtr& connection, const string& userId, bool allowAddUserMode, const SessionPrx& session, @@ -30,38 +48,70 @@ Glacier2::RouterI::RouterI(const ObjectAdapterPtr& clientAdapter, const ObjectAd _controlId(controlId), _timestamp(IceUtil::Time::now()) { - string allow = _communicator->getProperties()->getProperty("Glacier2.AllowCategories"); - StringSeq allowCategories; - - const string ws = " \t"; - string::size_type current = allow.find_first_not_of(ws, 0); - while(current != string::npos) + PropertiesPtr props = _communicator->getProperties(); + // + // DEPRECATED PROPERTY: Glacier2.AllowCategories is to be deprecated + // and superseded by Glacier2.Filter.Categories.Allow. + // + string allow = props->getProperty("Glacier2.AllowCategories"); + if(allow.empty()) { - string::size_type pos = allow.find_first_of(ws, current); - string::size_type len = (pos == string::npos) ? string::npos : pos - current; - string category = allow.substr(current, len); - allowCategories.push_back(category); - current = allow.find_first_not_of(ws, pos); + allow = props->getProperty("Glacier2.Filter.Category.Accept"); } - if(allowAddUserMode && !_userId.empty()) + string reject = props->getProperty("Glacier2.Filter.Category.Reject"); + bool acceptOverride = props->getPropertyAsIntWithDefault("Glacier2.Filter.Category.AcceptOverride", 0) == 1; + + vector<string> allowSeq; + vector<string> rejectSeq; + stringToSeq(allow, allowSeq); + stringToSeq(reject, rejectSeq); + + int addUserMode = props->getPropertyAsInt("Glacier2.AddUserToAllowCategories"); + if(addUserMode == 0) + { + addUserMode = props->getPropertyAsInt("Glacier2.Filter.Category.AddUser"); + } + + if(addUserMode > 0 && !_userId.empty()) { - int addUserMode = _communicator->getProperties()->getPropertyAsInt("Glacier2.AddUserToAllowCategories"); if(addUserMode == 1) { - allowCategories.push_back(_userId); // Add user id to allowed categories. + allowSeq.push_back(_userId); // Add user id to allowed categories. } else if(addUserMode == 2) { - allowCategories.push_back('_' + _userId); // Add user id with prepended underscore to allowed categories. + allowSeq.push_back('_' + _userId); // Add user id with prepended underscore to allowed categories. } - } + } + StringFilterIPtr categoryFilter = new StringFilterI(allowSeq, rejectSeq, acceptOverride); - sort(allowCategories.begin(), allowCategories.end()); // Must be sorted. - allowCategories.erase(unique(allowCategories.begin(), allowCategories.end()), allowCategories.end()); + // + // TODO: refactor initialization of filters. + // + allow = props->getProperty("Glacier2.Filter.AdapterId.Accept"); + reject = props->getProperty("Glacier2.Filter.AdapterId.Reject"); + acceptOverride = props->getPropertyAsIntWithDefault("Glacier2.Filter.AdapterId.AcceptOverride", 0) == 1; + stringToSeq(allow, allowSeq); + stringToSeq(reject, rejectSeq); + StringFilterIPtr adapterIdFilter = new StringFilterI(allowSeq, rejectSeq, acceptOverride); + // + // TODO: Object id's from configurations? + // + IdentitySeq allowIdSeq; + IdentitySeq rejectIdSeq; + IdentityFilterIPtr objectIdFilter = new IdentityFilterI(allowIdSeq, rejectIdSeq, false); + + const_cast<StringFilterPrx&>(_categoryFilter) = + StringFilterPrx::uncheckedCast(_adminAdapter->addWithUUID(categoryFilter)); + const_cast<StringFilterPrx&>(_adapterIdFilter) = + StringFilterPrx::uncheckedCast(_adminAdapter->addWithUUID(adapterIdFilter)); + const_cast<IdFilterPrx&>(_objectIdFilter) = + IdFilterPrx::uncheckedCast(_adminAdapter->addWithUUID(objectIdFilter)); const_cast<ClientBlobjectPtr&>(_clientBlobject) = new ClientBlobject(_communicator, _routingTable, - allowCategories); + categoryFilter, adapterIdFilter, + objectIdFilter); if(serverAdapter) { @@ -109,6 +159,13 @@ Glacier2::RouterI::destroy() try { _adminAdapter->remove(_controlId); + + // + // Remove filter objects. + // + _adminAdapter->remove(_objectIdFilter->ice_getIdentity()); + _adminAdapter->remove(_adapterIdFilter->ice_getIdentity()); + _adminAdapter->remove(_categoryFilter->ice_getIdentity()); } catch(const NotRegisteredException&) { @@ -210,6 +267,24 @@ Glacier2::RouterI::getServerBlobject() const return _serverBlobject; } +StringFilterPrx +Glacier2::RouterI::getCategoryFilter() const +{ + return _categoryFilter; +} + +StringFilterPrx +Glacier2::RouterI::getAdapterIdFilter() const +{ + return _adapterIdFilter; +} + +IdFilterPrx +Glacier2::RouterI::getObjectIdFilter() const +{ + return _objectIdFilter; +} + SessionPrx Glacier2::RouterI::getSession() const { diff --git a/cpp/src/Glacier2/RouterI.h b/cpp/src/Glacier2/RouterI.h index 9c3c73f37b9..15327641606 100644 --- a/cpp/src/Glacier2/RouterI.h +++ b/cpp/src/Glacier2/RouterI.h @@ -43,6 +43,9 @@ public: ClientBlobjectPtr getClientBlobject() const; ServerBlobjectPtr getServerBlobject() const; + StringFilterPrx getCategoryFilter() const; + StringFilterPrx getAdapterIdFilter() const; + IdFilterPrx getObjectIdFilter() const; SessionPrx getSession() const; @@ -56,6 +59,9 @@ private: const RoutingTablePtr _routingTable; const Ice::ObjectPrx _clientProxy; const Ice::ObjectPrx _serverProxy; + const StringFilterPrx _categoryFilter; + const StringFilterPrx _adapterIdFilter; + const IdFilterPrx _objectIdFilter; const ClientBlobjectPtr _clientBlobject; const ServerBlobjectPtr _serverBlobject; const Ice::ObjectAdapterPtr _adminAdapter; diff --git a/cpp/src/Glacier2/SessionRouterI.cpp b/cpp/src/Glacier2/SessionRouterI.cpp index 4e10b51ebef..8725c628505 100644 --- a/cpp/src/Glacier2/SessionRouterI.cpp +++ b/cpp/src/Glacier2/SessionRouterI.cpp @@ -34,6 +34,29 @@ public: { } + virtual StringFilterPrx + categoryFilter(const Current& current) + { + return _sessionRouter->getRouter(_connection, + current.adapter->getCommunicator()-> + stringToIdentity("dummy"))->getCategoryFilter(); + } + + virtual StringFilterPrx + adapterIdFilter(const Current& current) + { + return _sessionRouter->getRouter(_connection, + current.adapter->getCommunicator()-> + stringToIdentity("dummy"))->getAdapterIdFilter(); + } + + virtual IdFilterPrx + objectIdFilter(const Current& current) + { + return _sessionRouter->getRouter(_connection, current.adapter->getCommunicator()-> + stringToIdentity("dummy"))->getObjectIdFilter(); + } + virtual void destroy(const Current&) { diff --git a/cpp/src/Glacier2/glacier2router.dsp b/cpp/src/Glacier2/glacier2router.dsp index 2181f9dccf2..cce9336ed90 100755 --- a/cpp/src/Glacier2/glacier2router.dsp +++ b/cpp/src/Glacier2/glacier2router.dsp @@ -115,6 +115,10 @@ SOURCE=.\CryptPermissionsVerifierI.cpp # End Source File
# Begin Source File
+SOURCE=.\FilterI.cpp
+# End Source File
+# Begin Source File
+
SOURCE=.\glacier2router.cpp
# End Source File
# Begin Source File
@@ -159,6 +163,10 @@ SOURCE=.\CryptPermissionsVerifierI.h # End Source File
# Begin Source File
+SOURCE=.\FilterI.h
+# End Source File
+# Begin Source File
+
SOURCE=.\RequestQueue.h
# End Source File
# Begin Source File
diff --git a/cpp/src/Slice/slice.dsp b/cpp/src/Slice/slice.dsp index a92aad74c19..9db12e117dd 100644 --- a/cpp/src/Slice/slice.dsp +++ b/cpp/src/Slice/slice.dsp @@ -44,7 +44,7 @@ RSC=rc.exe # PROP Target_Dir ""
# ADD BASE CPP /nologo /MT /W3 /GX /O2 /D "WIN32" /D "NDEBUG" /D "_WINDOWS" /D "_MBCS" /D "_USRDLL" /D "PARSER_EXPORTS" /Yu"stdafx.h" /FD /c
# ADD CPP /nologo /MD /W3 /WX /GR /GX /O2 /I ".." /I "../../include" /I "dummyinclude" /D "_USRDLL" /D "SLICE_API_EXPORTS" /D "_CONSOLE" /D "NDEBUG" /D "WIN32_LEAN_AND_MEAN" /FD /c
-# SUBTRACT CPP /Z<none> /Fr /YX
+# SUBTRACT CPP /Fr /YX
# ADD BASE MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD MTL /nologo /D "NDEBUG" /mktyplib203 /win32
# ADD BASE RSC /l 0x409 /d "NDEBUG"
@@ -54,8 +54,7 @@ BSC32=bscmake.exe # ADD BSC32 /nologo
LINK32=link.exe
# ADD BASE LINK32 kernel32.lib user32.lib gdi32.lib winspool.lib comdlg32.lib advapi32.lib shell32.lib ole32.lib oleaut32.lib uuid.lib odbc32.lib odbccp32.lib /nologo /dll /machine:I386
-# ADD LINK32 /nologo /dll /pdb:none /machine:I386 /out:"Release/slice31.dll" /implib:"Release/slice.lib" /FIXED:no
-# SUBTRACT LINK32 /debug
+# ADD LINK32 /nologo /dll /machine:I386 /out:"Release/slice31.dll" /implib:"Release/slice.lib" /FIXED:no
# Begin Special Build Tool
OutDir=.\Release
SOURCE="$(InputPath)"
|